java面向对象

面向对象

Java 的核心思想就是OOP。

面向过程 & 面向对象

  1. 面向过程思想

    • 步骤清晰简单,第一步做什么,第二步做什么……

    • 面向过程适合处理一些较为简单的问题。

  2. 面向对象思想

    • 物以类聚,分类的思维模式,思考问题首先会解决问题需要哪些分类,然后对这些分类进行单独思考。最后,才对某个分类下的细节进行面向过程的思索。

    • 面向对象适合处理复杂的的问题,适合处理需要多人协作的问题~

对于描述复杂的事物,为了从宏观上把握、从整体上合理分许,我们需要使用面向对象的思路来分许整个系统。但是,具体到围观操作,仍然需要面向过程的思路去处理。


什么是面向对象

  • 面向对象编程(Object-Oriented Programming OOP)

  • 面向对象编程的本质就是:以类的方式组织代码,以对象的形式封装数据。

  • 抽象

  • 三大特性:

    1. 封装

    2. 继承

    3. 多态

  • 从认识论角度考虑是先有对象后有类。对象,是具体的事物。类,是抽象的,是对对象的抽象。

  • 从代码运行角度考虑是现有类后又对象。类是对象的模板。


类与对象的关系

  1. 雷士一种抽象的数据类型,它是对某一类事务整体描述/定义,但是并不能代表某一个具体的事物。

    • 动物、植物、手机、电脑……等抽象的事物。

    • Person类、Pet类、Car类等,这些类都是用来描述/定义某一类具体的事物应该具备的特点和行为。

  2. 对象是抽象概念的具体实例

    • 比如张三就是人的一个具体的实例,张三家里的旺财就是狗的一个具体的实例。

    • 能够体现出特点,展现出功能的是具体的实例,而不是抽象的概念。


创建与初始化对象

  • 使用 new 关键字创建对象。

  • 使用 new 关键字创建的时候,除了分配内存空间之外,还会给 创建好的对象 进项默认的初始化以及 对类中构造器的调用。

一个项目应该只存在一个 main 方法。

代码实现:

 // Student类
 public class Student {
  // 属性:字段
  String name;
  int age;
 
  // 方法
  public void study(){
  System.out.println(this.name+"在学习");
  }
 }
 // App类
 public class App {
  public static void main(String[] args) {
  // 类:抽象的,实例化
  // 类实例化后会返回一个自己的对象!
  // 对象student就是Student类的具体实例!
  Student student = new Student();
 
  Student XM = new Student();
 
  System.out.println(XM.name); //null 默认初始化
 
  XM.name = "小明";
  XM.age = 14;
  System.out.println(XM.name); // 小明
  System.out.println(XM.age); // 14
  XM.study(); // 小明在学习
 
  }
 }

构造器:

  • 类中的构造器也称为构造方法,是在进行创建对象的时候必须要调用的。并且构造器有一下两个特点:

    1. 必须和类的名字相同。

    2. 必须没有返回类型,也不能写void。

代码实现:

 public class Person {
  String name;
  // 一个类即使什么都不写,他也会存在一个方法
 
  // 1. 使用 new 关键字,本质是在调用构造器
  // 2. 用来初始化值
  public Person(){
 
  }
  // 有参构造:一旦定义了有参构造,无参就必须显示出来,否则报错
  public Person(String name){
  this.name = name;
  }
 }
 public class App {
  public static void main(String[] args) {
  // new 实例化一个对象
  Person person = new Person("龙");
 
  System.out.println(person.name);
  }
 }
  • 作用:

    1. new 本质在调用构造方法。

    2. 初始化对象的方法

  • 注意:

    1. 定义了有参构造之后,无参构造必须显示出来,否则报错。

  • Alt + Insert


super & this

直接上代码!:

 public class Person {
  public String name = "我是Person";
 
  // 私有的内容可以被继承,但不能访问!
  public void print(){
  System.out.println("Person方法");
  }
 
  public Person(){
  System.out.println("Person构造器");
  }
 }
 // ================================================
 public class Student extends Person{
  private String name = "我是Student";
 
  public void test(String name){
  System.out.println(name); // 我是test
  System.out.println(this.name); // 我是Student
  System.out.println(super.name); // 我是Person
  }
 
  public void print(){
  System.out.println("Student方法");
  }
 
  public void test1(){
  print(); // Student方法
  this.print(); // Student方法
  super.print(); // Person方法
  }
 
  public Student(){
  // 隐藏代码:默认调用了父类的’无参构造‘
  super(); // 必须要在子类构造器的第一行。
  // this();也是要在构造器第一行,因此不可同时存在。
  System.out.println("Student构造器");
  //Person构造器
  //Student构造器
  }
 }
 public class App {
  public static void main(String[] args) {
  Student student = new Student();
 
  student.test("我是test");
  student.test1();
  }
 }

super 注意点:

  1. super调用父类的构造方法,必须在构造方法的第一个

  2. super必须只能出现在子类的方法或者构造方法中

  3. super 和 this 不能同时调用构造方法

super 和 this 注意点:

  1. 代表的对象不同 this:调用本类中的对象 super:代表父类对象的调用

  2. 前提 this:没有继承也可以使用 super:只能在继承条件下可以使用

  3. 构造方法 this();本类的构造 super();父类的构造

重写:需要有继承关系,子类重写父类的方法!

  1. 方法名必须相同

  2. 参数列表必须相同

  3. 修饰符:范围可以扩大但不能缩小:public>protected>default>private

  4. 抛出的异常:范围,可以被缩小,但不能扩大:ClassNotFoundException --> Exception

  5. 静态方法 static 不能重写


### 封装

 

  • 通俗理解就是:该漏的漏,该藏的藏。

    • 程序设计要追求“高内聚,低耦合”。高内聚:类的内部数据操作细节自己完成,不允许外部干涉;低耦合:仅暴露少量的方法给外部使用。

  • 封装(数据的隐藏)

    • 通常,应禁止直接访问一个对象中数据的实际表示,儿应通过操作接口来访问,这成为信息隐藏。

  • 一句话:属性私有,get/set

  • 优点:

    1. 良好的封装能够减少耦合。

    2. 类内部的结构可以自由修改。

    3. 可以对成员变量进行更精确的控制。

    4. 隐藏信息,实现细节。

代码实现:

 public class Father {
  // 属性私有
  private int money;
  private String name;
 
  // 上面的money属性设置为私有的,只有本类才能访问,其他类都访问不了,如此就对信息进行了隐藏。
  // 对每个值属性提供对外的公共方法访问,也就是创建一对赋取值方法,用于对私有属性的访问,例如:
 
  // get 获得这个数据
  public int getMoney(){
  return this.money;
  }
  // set 给这个数据设置值
  // 可以在 set 做一些验证判断
  public void setMoney(int money){
  if (money>1000 || money<=0){
  this.money = 10;
  }else {
  this.money = money;
  }
  }
 }
 // =================================================================================================
 public class Sun {
  public static void main(String[] args) {
  Father f = new Father();
  f.setMoney(5000); // 对私有money进行赋值
  f.setName("小龙"); // 对私有name进行赋值
  System.out.println(f.getMoney()); // 10
  System.out.println(f.getName()); // 小龙
  }
 }
  • 封装的意义:

    1. 提高程序的安全性,保护数据。

    2. 隐藏代码的实现细节。

    3. 统一接口。

    4. 系统可维护性增加了。


继承

  • 继承的本质是对某一批类的抽象,从而实现对现实世界更好的建模。

  • extends 的意思是“扩展”。子类是父类的扩展。

  • Java中类只有单继承没有多继承!

     

  • 继承是类和类之间的一种关系。除此之外,类和类之间的关系还有依赖、组合、聚合等。

  • 继承关系的两个类,一个为子类(派生类),一个为父类(基类)。子类继承父类,使用关键字 extends 来表示。

  • 子类和父类之间,从意义上将应该具有 “is a” 的关系。

    object 类

    super

    方法重写

代码实现:

 public class Person /*extends Object*/{
  // Ctrl + H
  //Object 是所有类的默认父类,直接或间接继承
  private int money;
  public void say(){
  System.out.println("滴滴");
  }
 
  public int getMoney() {
  return money;
  }
  public void setMoney(int money) {
  this.money = money;
  }
 }
 // ==================================================
 // 子类继承里父类,就会拥有父类的全部方法
 public class Student extends Person{
 
 }
public class App {
public static void main(String[] args) {
Student student = new Student();
student.say(); // 滴滴
student.setMoney(100000000);
System.out.println(student.getMoney()); // 100000000
}
}

方法的重写规则

  • 参数列表与被重写方法的参数列表必须完全相同。

  • 返回类型与被重写方法的返回类型可以不相同,但是必须是父类返回值的派生类(java5 及更早版本返回类型要一样,java7 及更高版本可以不同)。

  • 访问权限不能比父类中被重写的方法的访问权限更低。例如:如果父类的一个方法被声明为 public,那么在子类中重写该方法就不能声明为 protected。

  • 父类的成员方法只能被它的子类重写。

  • 声明为 final 的方法不能被重写。

  • 声明为 static 的方法不能被重写,但是能够被再次声明。

  • 子类和父类在同一个包中,那么子类可以重写父类所有方法,除了声明为 private 和 final 的方法。

  • 子类和父类不在同一个包中,那么子类只能够重写父类的声明为 public 和 protected 的非 final 方法。

  • 重写的方法能够抛出任何非强制异常,无论被重写的方法是否抛出异常。但是,重写的方法不能抛出新的强制性异常,或者比被重写方法声明的更广泛的强制性异常,反之则可以。

  • 构造方法不能被重写。

  • 如果不能继承一个类,则不能重写该类的方法。

class Animal{
public void move(){
System.out.println("动物可以移动");
}
}

class Dog extends Animal{
public void move(){
System.out.println("狗可以跑和走");
}
}

public class TestDog{
public static void main(String args[]){
Animal a = new Animal(); // Animal 对象
Animal b = new Dog(); // Dog 对象

a.move();// 执行 Animal 类的方法

b.move();//执行 Dog 类的方法
}
}
以上实例编译运行结果如下:

动物可以移动
狗可以跑和走
class Animal{
public void move(){
System.out.println("动物可以移动");
}
}

class Dog extends Animal{
public void move(){
System.out.println("狗可以跑和走");
}
public void bark(){
System.out.println("狗可以吠叫");
}
}

public class TestDog{
public static void main(String args[]){
Animal a = new Animal(); // Animal 对象
Animal b = new Dog(); // Dog 对象

a.move();// 执行 Animal 类的方法
b.move();//执行 Dog 类的方法
b.bark();
}
}
以上实例编译运行结果如下:

TestDog.java:30: cannot find symbol
symbol : method bark()
location: class Animal
b.bark();
^

多态

  • 即统一方法可以根据发送对象的不同而采用多种不同的行为方式。

  • 一个对象的实现类型是确定的,但可以指向对象的引用类型有很多(父类,有关系的类)。

     

  • 多态存在的条件

    1. 有继承关系。

    2. 子类重写父类方法。

    3. 父类引用指向子类对象。 Parent p = new Child();

     

  • 注意:多态是方法的多态,属性没有多态性。

  • instanceof (类型转换) 引用类型。

代码实现:

public class Person {
public void run(){
System.out.println("run");
}
}

// ====================================================================================
public class Student extends Person{
@Override
public void run() {
System.out.println("son");
}

/*

“子类没有重写父类调用父类 子类重写父类调用子类”

一.多态注意事项;
1. 多态是方法,属性没有多态
2. 父类和子类,有联系 类型转换异常 --> ClassCastException
3. 存在条件: 继承关系,方法需要重写,父类引用指向子类对象 --> Father f1=new Son();
(实例方法和类方法也分别称为非静态方法和静态方法)
static 静态方法,属于类不属于实例
final 常量
private 方法

二.多态存在的三个必要条件
继承
重写
父类引用指向子类对象:Parent p = new Child();

b是Anew出来的对象,因此调用了A的方法
“静态属于类,非静态属于对象”
有static时,b调用了B类的方法,因为b是用B类定义的
没有static时,b调用了对象的方法,因为b是用B类new出来的
A a = new A();
a.test;
B b = new A();
b.test;
*/
}

 

public class App {
public static void main(String[] args) {
/*
如果子类没有重写 父类调用父类;如果子类重写 父类调用子类
子类继承父类的所有方法
父类无法调用子类独有的方法
*/
//一个对象的实际类型是确定的
//new Student();
//new Person();

//可以指向的引用类型就不确定了:父类的引用指向子类

//Student 能调用的方法都是自己的或者继承父类的
Student s1 = new Student();
//Person 父类型,可以指向子类,但是不能调用子类独有的方法
Person s2 = new Student();
Object s3 = new Student();

//对象能执行哪些方法,主要看对象左边的类型,和右边关系不大
s2.run();//子类重写了父类的方法,执行子类的方法
s1.run();

//被 final 修饰的类不能被继承
}
}

// 输出结果:
son
son

注:

  • “子类没有重写父类调用父类 子类重写父类调用子类”

  • 如果子类没有重写 父类调用父类;如果子类重写 父类调用子类, 子类继承父类的所有方法, 父类无法调用子类独有的方法。

  • 被 final 修饰的类不能被继承。


instanceof 关键字

代码实现:

// 理解为一个树状图
//Object > String
//Object > Person > Teacher
//Object > Person > Student

Person person=new Student();
System.out.println(person instanceof Student);//true
System.out.println(person instanceof Person);//true
System.out.println(person instanceof Object);//true
System.out.println(person instanceof Teacher);//false
//System.out.println(person instanceof String);//编写报错

作用:作用是测试它左边的对象是否是它右边的类的实例,返回 boolean 的数据类型。(测试两边是否存在子父级关系,返回布尔值,毫无关系报错)


强制类型转换

  1. 低(子)转高(父):向上转型。

    直接转,丢失子类中原本的可直接调用的特有方法;

  2. 高(父)转低(子):向下转型。

    强制转,丢失父类被子类所重写的方法。

  • 方便方法的调用,减少重复的代码

代码实现:

public class Add {
public static void main(String[] args) {
//类型之间的转化:父 子

//高 底
Person obj = new Student();
//父类不能调用子类独有的方法,需要强制转换

// Student student = (Student) person;
// student.go();
((Student)obj).go();

//子类转换为父类,将丢失自己的本来的一些方法
/*
低(子)转高(父)时,由于子已经继承了父的所有,
所以删去属于自己的后自然而然就可以转化问父类的;
而父想要转子,则需要重新开辟只属于子的空间,则需用强制转换
*/
Student student = new Student();
student.go();
}
}

static 关键字

代码实现:

public class Student {
private static int age; // 静态方法
private double score; // 非静态方法

public void go(){}
public static void run(){}

public static void main(String[] args) {
Student s1 = new Student();

// 惊天变量对于类,所有对象(实例)所共享,能够直接使用类去调用得到说明这个变量是静态变量
System.out.println(Student.age);
//System.out.println(Student.score); // 报错
System.out.println(s1.age);
System.out.println(s1.score);

Student.run();
run();
// static 和 class 同时加载,静态加载了非静态都没加载出来自然无法调用
//go();

/*
static 这里的意思是,原本Java文件编译成class文件,如果有static关键字,就会一起加载进去初始化,
没有static的话,就需要new了才会加载,jvm比较懒,不会全部加载。
*/
}
}

匿名打码块

import static java.lang.Math.random;
// final修饰符 不能被继承
public final class Person {
//2.
{
System.out.println("匿名代码块");
}
//1.只执行一次
static {
System.out.println("静态代码块");
}
//3.
public Person() {
System.out.println("构造方法");
}

public static void main(String[] args) {
Person person = new Person();
System.out.println("================");
Person person1 = new Person();
System.out.println(random());
System.out.println(Math.PI);
}
}
// 运行结果:
静态代码块
匿名代码块
构造方法
================
匿名代码块
构造方法
0.5873660822965209
3.141592653589793

 

posted @ 2021-04-29 10:43  C_Long  阅读(312)  评论(0)    收藏  举报