1、整理面向对象笔记
Java的程序主要是靠类,类中存放的是成员变量或者成员方法。
Java程序是需要交给JVM运行。JVM会从硬盘上加载指定的class文件到内存中。开始执行这个程序。
class Demo{
public static void main(String[] args)
{
int a = 10;
double d = 3.14;
if( a % 2 == 0 ){
System.out.println(“a是偶数”);
}
}
}
JVM在执行程序的过程中,我们书写的各种逻辑,最后需要Java中提供的关键字来处理。而JVM会识别这些关键字,当JVM在执行程序的过程中,遇到不同的关键字,JVM知道做不同的事情。
Java语言是解决生活中的问题:
Java对生活中的所有事物进行了描述。Java中采用的对象来代表生活中各种各样的事物(个体)。
这些个体我们没有办法去描述的十分具体形象,而一般都会稍微有个抽象的总结。
在Java中把某些事物进行归纳之后,一般会采用他们的共同的属性和行为来描述。负责描述这个事物的代码程序类。
Java中使用类表示:生活中的某一类事物。而在生活中面对的是这个事物中某个个体,在Java中要想使用具体的个体,就必须使用new关键字,创建出描述这类事物的那个类的具体对象。
面向对象的特征:面向的对象的三个特征他们都是思想上的。
封装、继承、多态。
封装:把不需要外界直接接触的内容全部包装起来,然后如果外界还需要操作,这时可以通过间接的方式提供出去。
Java中的体现:把类中不需要其他类直接访问的成员变量,或者成员方法,或构造方法使用private关键字修饰。一般 在开发中成员变量私有,对外提供get或set方法。
继承:Java中的类是描述生活中的某一类事物,但是在生活中事物和事物之间会有一定的关系。我们使用Java中的类把不同的事物都描述清楚之后,也需要维护这些事物之间的关系。那么就需要使用Java中的继承。extends关键字完成。
继承的使用场景:两个类之间存在必然的联系,两个类它们属于同一个事物体系。
继承中的成员变量:
父类的成员变量子类是可以继承到的。如果是私有的,子类继承到了,但是子类没有权限使用。
当子父类中出现了同名的成员变量,并且没有私有的情况下,在子类中如果要使用父类的成员变量需要使用super.成员变量名。
继承中的成员方法:
父类的成员方法没有私有,子类可以直接使用。
当子父类中出现了一模一样的方法时:称为方法的重写(复写override)
方法重写的特点:
1、 子类复写父类方法的时候,要求方法的返回值,方法名,方法的参数必须相同
2、 方法的修饰符,子类复写时可以大于等于父类的修饰符
3、 子类在复写父类的方法时,不能修改方法的访问方式。(类名调用,或者对象调用)
继承中的构造方法:
在子类的构造方法中,如果没有使用this()语句,调用本类的其他构造方法,那么在这个构造方法中就会有super()语句,调用父类的构造方法。(构造方法中有super语句的原因是:子类继承了父类,会继承到父类的成员变量,而成员变量的初始化动作是需要本类自己的构造方法完成,而子类继承到父类成员变量,有不能对父类成员变量进行初始化,因此在子类的构造方法中使用super语句调用父类的构造方法,目的是给当前继承到的这个父类的成员变量进行显示初始化)。
如果父类中没有空参数的构造方法,子类的构造方法中必须手动显示指定调用父类的那个有参数的构造方法。
如果一个类中的构造方法全部私有了,这个类还能不能有子类:
不能。因为构造方法全部私有,在本类以外的其他类中是无法访问使用的, 如果有子类,子类的构造方法中的super语句,没有办法找到父类的构造方法。
this:表示的是当前调用这个方法的那个具体的对象。
this.成员变量名
this.成员方法();
this调用本类其他的构造方法
super:一般用在子类中,表示父类的成员变量,或者成员方法,或者调用父类的构造方法
this可以单独直接使用,但是super必须显示指定需要调用的父类内容。
static:静态,修饰类中的成员变量和成员方法。
静态不能调用非静态,但是非静态可以调用静态。
因为静态的成员在使用的时候,并不一定有对象,但是非静态的成员使用的时候,肯定已经有对象了。
private:修饰类中的成员(方法,变量,构造方法)。
final:表示最终化。
可以修饰类,成员变量,成员方法,局部变量。
final修饰的类:这个类是最终类,不能再有子类。
final修饰的成员方法:假设这个类可以被继承,但是这个类中被final修饰的方法不能被子类复写。
final修饰的变量:这个变量空间中的数据不能被修改,因此这个变量名一般要求全部大写。
问题:被final修饰的变量如果是一个引用变量,那么这个引用变量所指的对象空间中的数据能不能改变?
可以。这个引用变量不能变。但是变量所指的对象中的数据可以变。
多态是面向对象中的第三个特征:
多态:把具体的某个事物(对象、个体、实例)使用它的另外一种形式描述。这个时候,我们就称当前这个事物被以多种形态展示出来。这种现象称为事物的多态性。
总结:多态就是把具体的一个事物采用其他的形态进行描述或者展示。但是这个事物的本身是没有发生任何变化的。
Java中对多态的体现:
格式:父类或者接口类型 引用变量名 = new 子类();
Animal an = new Cat(); 把猫这个具体的动物,使用Animal类型进行描述。这种现象称为多态。
水果 sg = new 苹果(); 多态
Java中的多态:把子类对象使用父类类型描述(表示)。父类的引用指向子类对象。
多态的前提:要求必须有继承或者实现(接口)。一般情况下会存在方法的复写。
多态的好处:可以通过父类或者接口统一去管理操作自己的子类对象。在开发中一般情况下,我们书写代码的时候,都会先去查阅这个些类的一个继承关系,使用父类类型引用指向一个具体的子类对象。
这种方式屏蔽了多个子类的之间的差异。
多态的弊端:
只要有多态的出现,肯定是把一个子类对象赋值给了父类的引用,这时使用这个引用是没有办法去调用子类对象中自己的特有方法。
多态的转型:
只要在代码中出现了多态现象,这时就发生了类型的向上转型。
在Animal a = new Cat();和Animal b = new Dog();
中把具体的Cat类型或者Dog类型转成了Animal类型。这种现象发生之后,不能去使用子类的特有方法。
如果想使用子类的特有方法,必须使用Java中提供的向下转型完成。
向上转型:父类 引用 = new 子类()
向下转型:子类 引用 = (子类类型)父类引用;
多态:会发生自动的向上转型。
如果需要使用子类特有的功能,就需要向下转型。
只要是向下转型,就有可能发生ClassCastException。为了在程序中避免这个异常,需要在转型之前对被转的数据进行类型的判断。
判断某个引用指向的对象到底是什么类型:
if( 被转的引用变量 instanceof 转后的类型 )
{
向下转型有风险,使用需判断(谨慎)。
目前学过的三个异常:
NullPointerException 空指针异常
ArrayIndexOutOfBoundsException 数组下标越界异常
ClassCastException 类型转换异常
多态中对象调用:
多态中成员变量调用:编译和运行使用的都是父类引用中成员变量。
非静态方法使用多态调用:编译需要看父类中是否有调用的方法,但运行的时候,用的是子类自己的。
静态方法调用的时候:编译运行都需要参考引用变量(父类)所属类中的方法。
抽象类:
如果我们在描述某个事物的时候,事物中有些行为我们知道应该具备,
但是方法体有不知道该如何书写,这时可以使用Java中提供的抽象方法表示。
方法的定义格式:
修饰符 返回值类型 方法名(参数列表)
{
方法体
}
抽象方法的格式:
修饰符 abstract 返回值类型 方法名(参数列表);
注意:
方法的定义后面如果有大括号,不管大括号中书写的是什么,都表示这个方法是有方法体的。
如果书写抽象方法,肯定不能书写大括号。必须以分号。
抽象类依然是个类,它也具备类的基本特定:
抽象类可以有父类。可以有子类。可以有构造方法等。
抽象类中的抽象方法是要求子类用来复写的。抽象类仅仅只是在定义这个事物体系应该具备什么功能,但是功能体由自己的子类完成。如果子类不复写,子类依然是个抽象类
抽象类是不能够创建对象的:
原因:抽象类中有抽象方法,如果可以创建对象, 那么就可以调用抽象方法,而我们调用方法的目的是需要执行方法体,得到具体的结果,抽象类中的抽象方法是没有方法体,调用是没有意义的。因此Java中规定不能创建抽象类的对象。
抽象类的特点:
1、抽象类一定是父类吗?
可以是父类。但它一定不是最顶层的父类。抽象类一定有子类。抽象类中的抽象方法需要子类复写。
2、抽象类中有构造方法吗?可以创建对象吗?
有构造方法。但是不能创建对象。抽象类需要子类继承,复写其中抽象方法。而子类的构造方法中有隐式的super语句,需要找到抽象类中的构造方法进行初始化。
3、抽象类中可以没有抽象方法吗?
可以。这个类存在的意义仅仅是不让创建这个类的对象。在讲接口的时候介绍原因。
4、抽象类中的构造方法可以全部私有吗?
不可以。一个的构造方法如果全部私有了,这个类是不能有子类的。
5、抽象关键字不能和哪些修饰符关键字一起使用?
private :原因是私有的成员方法只能在本类使用。而抽象方法是需要子类复写的。私有了,子类无法复写。
static :静态的成员方法可以通过类名直接调用,而抽象的方法如果使用static修饰,那么就可以使用类名直接调用这个抽象方法,调用抽象方法没有任何意义。
final:被final修饰的类,不能被继承,而抽象类是要求子类继承。被final修饰的方法是最终方法,子类无法复写,但是抽象方法要求子类必须复写。
接口:
如果我们在描述事物的时候,发现多个事物之间会有共性的行为, 但是这个行为又不是这个体系固有行为。这时可以使用Java中提供另外机制(接口)来保存这些事物体系中的额外功能。
接口的定义格式:
修饰符 interface 接口名
{
接口中的成员
}
类和接口之间产生关系:
类和类之间是继承关系,并且Java中只支持单继承。使用的extends关键字。
类和接口之间成为实现关系,需要使用java中提供的implements 关键字完成。
接口中的成员:
接口中只能定义成员变量和成员方法,没有其他的内容。
并且接口中的成员变量和成员方法有固定的修饰符:
变量:public static final 变量类型 变量名 = 值;
方法:public abstract 返回值类型 方法名( 参数类型 ) ;
由于接口中的变量或者方法的修饰符是固定的,因此全部可以省略不写。
接口和抽象类的区别:
抽象类:
抽象类依然是在描述事物体系,只是在描述的过程中,有些共性的行为无法描述具体,使用了抽象方法表示。导致这个类变成抽象类。
接口:它是给某个事物体系增加的了额外功能(扩展功能)。
类和类之间继承关系,并且一个类只能继承一个父类。
类和接口之间的关系:实现关系,并且一个类可以同时实现多个接口。Java中把多继承,改为了多实现。
多个接口中如果有同名的方法,他们都是抽象方法,这些方法都需要实现类做具体的方法实现。
接口和接口关系:它们之间是继承关系,并且支持多继承。
接口它有2大作用:
1、 给事物体系增加扩展(额外)功能。
2、 可以定义事物双方的规则。
适配器设计模式:
单例设计模式解决的问题:保证当前这个类的对象永远只有一个(对象的唯一性)。
适配器设计模式解决的问题:它主要是从接口过渡到真实的实现类之间的一个桥梁。
当我们需要使用一个接口中的部分方法时,这时一般都会给这个接口提供一个直接的实现类,但是在这个类中的所有方法都是空实现。并且把这个类书写成抽象类。当外界真的要使用接口的时候,这时不要去直接面对接口,而去继承,这个接口的实现类,把其中需要使用的方法重点复写,其他的方法可以不用处理。