Java基础总结--面向对象2
1.存在相关的多个方法就封装在一个类中,方法没调用到特有数据,需要静态化
2.假如一个类所有方法都是静态方法,为了保证不被其他创建对象,可以将该类的构造方法私有化
3.文档注释javadoc-按照规定注释--提取注释保存为Html格式(不重要按照规定来就行)
设计模式:对问题行之有效的解决方法--是一种思想
Java存在23种设计思想--OOP语言设计模式通用
------继承------
1.继承的概述
两个/多个类不断的对其进行向上的抽取其共性的东西--把这些共性的东西封装在父类中,产生父子关系--is a关系用关键字extends实现
2.继承的好处
代码复用、使得类之间产生关系、给后面的多态提供前提
3.Java中继承的特点:
**类之间只支持单继承--对于“多继承”是通过多实现完成(接口)
不直接支持多继承的原因:假如多个父类存在同一个方法,子类对象在调用方法的时候存在调用的不确定,所以不支持,而接口只是提供方法的声明,具体的实现要看子类的需要,所以不存在调用的不确定。
**存在多层继承--即存在继承体系
如果要使用一个继承体系的时候--首先要分析其顶层的类/接口(一般都是该体系最基本的功能)--要创建对象一般是选择创建子类的对象(原因既有继承的,也有自己的特有的内容)
4.关于继承的小细节
**不要盲目的使用继承--只有类之间存在强is a关系才考虑继承
**子类在继承时候会持有super关键字--代表父类空间(其实就是可以找到其父类)
区分父子类同名的成员:super;区分局部变量与本类对象:this
对于父类的私有成员变量,子类会继承,但是不可以访问而已
**this和super功能相似,但是super不代表是父类对象
**关于父子类在内存中加载--先加载父类再加载子类
**关于成员的调用:先在子类中找,其次没找到,才会在父类中找
**父子类成员方法的覆盖(重写)
覆盖出现的原因:子类想对继承到的功能进行修改
覆盖注意的细节:子类的覆盖方法的访问权限大于等于父类方法;静态覆盖静态/被静态覆盖
-----继承中子类对象实例化的过程----
1.JVM会读取制定路径下的该类的类文件,并加载进去内存,同时会加载其直接父类
2.在堆中开辟空间,分配地址
3.并在堆中对该子类对象进行默认初始化
4.然后才会调用其构造函数初始化,但是会首先默认调用父类的构造函数初始化
5.父类初始化完成后,子类的构造函数才会对对象进行显示初始化
6.初始化完后,会将堆中对象的地址赋值给栈中对象的引用,该引用指向该对象
注意:一般未指定会调用super(),当然也可以指定特定的父类构造函数初始化,假如找不到对应的父类构造函数,就会出现编译失败
---final关键字---修饰符
1.修饰类--不可以被继承
2.修饰成员变量--是一个常量,只能赋值一次,一般会加static修饰
数值如果是固定的--最好定义为常量,书写规范:所有字母大写且用下划线分隔多个单词
3.修饰成员方法---不可以被覆盖
------抽象类------出现的原因就是不同的子类对从父类继承的方法有自己独特的实现方式
1.概念:一旦含有抽象方法的类(可以不含有抽象方法,但是一般不这样写)必须用abstract修饰,定义为抽象类
抽象方法:只有方法头,没有方法体,用abstract修饰
2.特点
抽象类不能实例化--不能用new创建对象--调用抽象方法无意义
子类要继承抽象类必须重写父类所有的抽象方法(保证子类是一般类)
3.抽象类小细节
* 抽象类可以有构造函数--用于子类实例化
* 抽象类可以不定义抽象方法--这样不常见-AWT里面适配器类
* 抽象类不可以和那些关键字共存
this private(方法要被覆盖) static(静态不需要对象) final(不允许覆盖)
* 抽象类和一般类的区别
相同点:都是用来描述事物,都定义成员
不同点:一般类有足够的信息描述事物,抽象类描述事物信息不足;一般类中不能定义抽象方法,一般类可以被实例化,抽象类不可以被实例化
* 抽象类一定是父类--是的
------接口-------
1.概念
对外提供一种功能,其它的类想要拥有该功能,就直接实现该接口
定义接口:interface 接口名{成员变量;抽象方法}
接口中成员变量统一的修饰符:public static final
接口成员方法:public abstract
接口中这些修饰符可以省略,但是最好不要省略,影响阅读性
2.接口特点
不能实例化,对外提供一种某些功能
子类可以实现多个接口,接口之间也支持多继承
子类与接口之间,子类需要该功能,就实现该接口--子类与接口直接关系like a
子类与接口之间的关系较弱,主要用于扩展类的功能,用来降低类之间的耦合性
eg:USB接口--只要实现USB接口的功能,就可以用usb接口连接
3.接口的应用
先定义接口(就是规则)--以后的程序实现该接口(规则)
本来A,B之间的关系过于紧密,难于扩展和维护,所以就在设计的时候先定义一个接口,便于以后的扩展功能和维护
总结:1.接口定义规则和使用规则 2.实现规则
----多态-----
1.概述
定义:某类事物具有多种形态,eg猫,既属于猫类,也属于动物类别
多态出现的原因:之前用对象封装数据,但是随着创建越来越多的对象,使得问题变得复杂,所以就在这些对象中寻找其共性(让这些对象表现出其父类的共性--问题从子类对象代表本身转向只代表其父类的共性)
eg.猫吃东西,狗吃东西,小猪吃东西
其父类动物类也定义有吃东西,但是不同子类吃东西情况不一样,对该方法进行重写,假如想要调用子类吃东西的方法,一般做法创建子类对象,通过子类对象引用调用方法,这样做代码
复用性不好,也不利于后期代码的扩展
public static void eat(Cat c){c.eat();}
public static void eat(Dog d){d.eat();}
改进后代码
public static void eat(Animal a){a.eat();}//向里面传入子类对象,利于代码扩展
2.多态的好处
提高代码的扩展性
前期定义的代码可以使用后期定义代码的内容
3.多态的前提和弊端
前提:必须有继承,重写,父类引用指向子类对象
弊端:不能调用子类特有的内容(向上转型)
4.引用类型的转型
向上转型-upcasting
父类引用指向子类对象,把子类对象看作是父类的形态
Animal a = new Cat();a此时只显示出动物的性质 猫一定是动物,属于自动转型,此时对象引用a只能调用动物类定义的方法,不能访问猫特有的内容
向下转型-downcasting
Cat c = (int)a;-属于显示转型,此时c引用具备猫的一切内容,可以访问子类特有的内容
猫--上转--猫看作动物形态--下转--猫又回到猫自身的形态
注意:转型始终都是子类对象在进行状态的切换
----转型是否会成功----
1.向上转型一定会成功
2.向下转型就不一定,要看给父类传递的子类对象是否是要向下转型类的事例或子类实例
向下转型前通常对其进行判断 a(引用) instanceof B(类、接口)
即判断a实际类型是否是B类/接口的实例或其子类的实例
----多态存在下各个成员的变化------
成员变量的调用:编译(若未定义则编译失败)和运行时候都只看声明类型--因为子类已经被看作是父类特征,所以要去访问父类的属性
成员函数的调用(依赖的是对象,必须动态绑定):编译时候检测的是声明类型是否有该方法,运行时候调用子类重写的方法(覆盖方法只发生在成员函数上);运行时候引用代表的是子类对象的地址所以其执行的方法就是子类中重写的方法(依赖的是类);
静态函数的调用(依赖的是类,不依赖具体对象):根据编译运行都是按照声明类型调用
注意:静态方法其实都是通过类名直接调用的
成员变量,静态函数只看左边,成员函数,编译看左边,运行看左边(依赖于具体对象)
本质上多态:就是为了代码的扩展性
-----内部类----
1.作用:设计时候为了更好的组织类与类之间的关系,将一个类定义在另一个类的内部形成(外部封装类和内部类)
2.访问特点
内部类持有外部类引用,可以直接访问外部类所有成员
外部类要访问内部类的成员必须要建立内部类的对象
内部类必须有所属的外部类
内部类就是一个普通类,只不过定义在类的内部
3.什么时候使用:类的设计;分析事物,发现事物内部还有事物,且该事物要访问被描述事物的内容,此时就是把里面的类定义为内部类--相当于一种封装
4.内部类的的修饰符--内部类定义在外部类中成员的位置,可以用成员修饰符修饰类
private--只在本来中有效
default--在其他类中也可以直接访问该内部类(不常见--内部类通常被封装起来仅仅为本类服务)Outer.Inner in = new Outer().new Inner();--必须有所属外部类
static--相当于一个外部类 Outer.Inner in = new Outer.Inner();
如果内部类是静态的,成员就是静态的,内部类随着外部类的加载而加载不用创建外部类的对象,直接用类名调用静态成员。如果内部类定义静态成员,内部类必须定义为静态的
5.内部类的细节 Outer.this.num;内部类直接访问外部类的成员,原因:因为内部类持有外部类的引用 外部类.this--代表外部类的引用
6.局部内部类:将内部类放在方法内部---为了类的组织方便(用的不多),可以直接访问局部中被final修饰的局部变量的值
7.匿名内部类--是内部类的简写形式--为了方便
前提:内部类必须继承/实现一个外部类或接口 eg:事件监听器
eg:A 是一个内部类,继承抽象B类 new B(){重写抽象方法}
匿名内部类本质:就是一个匿名子类对象,简化封装
匿名内部类格式:new 父类/接口(){子类内容-重写抽象方法}--代表子类对象并重写抽象方法
匿名内部类的应用:
实现接口的抽象方法数不多小于3个,否则显得代码太多
可以使用匿名内部类作为实际参数进行传递