第五天学习面向对象
面向对象OOP
- 面向过程:步骤清晰,第一步做什么,第二步做什么。(处理简单问题)
- 面向对象:思考问题首先去给问题分类,对每个类别的问题单独思考,在解决每个小问题时还是借助面向过程来实现的。(处理复杂问题)以类的方式组织代码,以对象的形式封装数据。
- 类相当于模板,对象相当于具体实例。
- 抽象:把对象的共同点抽取出来(狗)。
- 实例:属于对象的个体(旺财)。
- 三大特性:封装,继承,多态。
构造器(构造方法)
- 方法名和类名相同,不能有返回值。
- 实例化对象本质是在调用构造器。
- 构造器是用来初始化值的。
- 添加有参构造后,无参构造就消失了,需手动定义。
内存分析
- 最开始先加载类进入方法区,在方法区开辟一块空间存放类中的方法,和常量(常量池中)
- 执行main()方法,将main()方法压入栈区。
- 在main()方法中对对象进行实例化后,会将对象的类加载进方法区(这时候方法区就开辟了一块区域,里面存在类下的属性和调用的方法)此时属性还没有被赋值,还是默认值。
- 当把new的方法赋值给对象后,在栈中会出现变量名的引用,真正new的对象的类在堆中,并生成一个内存地址(这时候初值没有变化),这时栈中的引用变量名会指向对应内存地址。
- 之后对对象进行赋值,从方法区开始向堆中的属性进行赋值。
- 内存中分为堆和栈,其中堆中又包括方法区和静态方法区
封装
-
封装就是将对象写在一个类中(属性私有),只留出一个接口可以控制类中的属性和方法(get/set)
-
封装可以提高程序的安全性,保护数据。
-
隐藏代码细节。
-
统一接口。
-
增加系统可维护性。
继承
- 继承即扩展,子类是父类的扩展,子类继承父类代码中为 子类 extends 父类。
- Java中所有的类都默认继承Object类。
- new子类后会先默认调用父类的构造方法(子类构造第一行默认super();)。
//子类重写了父类方法
1. 方法名必须相同。
2. 形参列表必须相同。
3. 修饰符范围可以扩大,不能缩小。
4. 抛出的异常范围可以被缩小,但不能扩大。
多态
-
通过多态可让程序可扩展性更强。
-
一个对象的实际类型是确定的,可以指向的引用类型是不确定的(父类的引用指向子类的类型)。
//静态方法的调用只和等号左边的类型有关。 A a = new A(); B b = new B(); //不能进行重写的方法 //1. static方法,它属于类,不属于实例。 //2. final为常量,存在于常量池中,不能被重写。 //3. private为私有方法,不能被重写。
-
子类重写了父类方法,调用默认调子类。没有重写,调父类。
-
子类能调用自己和父类(非private)的方法;父类不能调用子类独有的方法,但可进行类的强制转换(高转低)。
instanceof和类型转换
instanceof可以判断两个类是否存在父子类关系
//定义一个Person父类,他有Student和Teacher两个子类
Object o = new Student();
System.out.println(o instanceof Student);
System.out.println(o instanceof Person);
System.out.println(o instanceof Object);
System.out.println(o instanceof Teacher);
System.out.println(o instanceof String);
//输出:true true true flase flase
/--------------------------------
//Object > String
//Object > Person > Teacher
//Object > Person > Student
//instanceof只可判有父子关系的类,同级或不相关类返回flase
类型转换
所有类型转换都是 低 ----------->高 ,否则需要强制类型转换,对象类型也是。
// 父(高) <----- 子(低) 子类转父类可能会丢失一些自己的方法
Person p = new Student();
// 父类转换为子类也需要强制类型转换,之后就可以使用Student中独有的方法了
Student s = (Student)p;
static静态
-
静态修饰的变量和方法可以通过类或对象进行调用,非静态只能通过对象调用。
-
静态方法可以调用静态方法和属性,但不能调用非静态方法和属性,因为静态修饰的是和类一起在内存方法区中被创建的,创建静态方法和属性时,非静态的还没有被创建!
-
static修饰的内容只执行一次(同一方法new了两次,第二次static不执行)
-
在导包时加入static可直接导入类中的方法。(静态导入包)
abstract抽象
- 抽象方法只有方法名,没有方法体。
- 抽象类中的抽象方法必须被子类重写。
- 抽象类不能被实例化,只能靠子类实现。
- 抽象类中可有普通方法,抽象方法必须在抽象类中。
- 抽象类也有构造方法,一般是由子类继承抽象类时使用。
接口
- 接口的本质时契约,制定好标准后大家都要遵守。
- 接口只能定义抽象方法,而且默认public abstract。
- 接口都需要实现类,以Impl结尾命名,通过implements来实现接口,并且可以多实现(继承)。
- 接口没有构造方法。
内部类
-
类的内部再定义一个类。
-
内部类实例化必须先实例化外部类,再通过外部类实例化内部类
//实例化外部类 Outer outer = new Outer(); //通过外部类.new来实例化内部类 Outer.Inner inner = outer.new Inner();
-
内部类可以拿到外部类的私有属性和方法,但取不到static修饰的(因为static出生时非static类还没出生!)
-
在方法中也可以写class(局部内部类)