1.接口
接口中有抽象方法,但该方法没有方法体。
当某类实现某接口时,就必须提供该接口当中声明的方法。实现在语法上使用关键字implements。
2.对象转型
类与类之间的转换
-
明确引用类型和对象类型的概念
e . g .
ADHero ad=new ADHero(); //引用ad的类型是ADHero(第一个),引用指向的对象类型是ADHero(第二个)
-
转型:当引用类型和对象类型不一致的时候,就需要进行类型转换。
-
判断转型是否能够成功:可以把右边的对象类型当作左边使用。
栗子:
Hero h = new Hero(); ADHero ad = new ADHero(); h = ad; //最后一行ad的对象类型是ADHero,h的对象类型是Hero。右边ADHero是Hero吗?是,可以判断转型能够成功。
①子类转父类(向上转型)
所有的子类转父类都是可以成功的。子类对象赋值给父类类型的变量(父类引用类型 引用=new 子类对象();)
②父类转子类
假设一个引用1指向的对象类型是父类,另一个引用2指向的对象类型是子类。当1=2;(子类转父类)一定能成功,当2=1(父类转子类)则需要强制转换(子类 2=(子类)1)。
③没有继承关系的两个类互相转换
没有继承关系的两个类互相转换一定会失败。
类与接口之间的转换
①实现类转换成接口
接口中的抽象方法在实现类中实现。因为实现类转换成接口后,一定要调用对应接口中的抽象方法,且实现类中本来就有该方法,所以转换能够成功。
②接口转换成实现类
??
关键字instanceof:判断对象类型
当在程序中执行向下转型时,若父类对象不是子类对象的实例,就会发生ClassCastException异常,所以在执行向下转型之前要先判断父类对象是否为子类对象的实例。
myobject instanceof ExampleClass;
//myobject是某类(父类)的对象引用,ExampleClass(子类)指的是某个类。
//instanceof操作符的表达式返回的是布尔值。若返回true,说明myobject对象是ExampleClass的实例对象,否则不是。
3.重写
子类可以继承父类的对象方法。在继承后,重复提供已经继承的对象方法就叫做重写(又叫做覆盖override)。
在子类中,出现了和父类方法声明完全一样的方法就是方法重写。方法名,参数列表,返回值类型都一样,只是方法体不一样。
4.多态
-
操作符的多态,如:“+”可以作为算术运算符,也可以作为字符串连接符。
-
类的多态:父类引用指向子类对象。(父类引用类型 引用=new 子类对象类型();)
JAVA中没有多继承的概念,一个子类只能继承一个父类,但父类能有多个子类。不同子类重写父类的方法时,由于方法体不同,呈现的结果也不一样。当父类引用指向子类对象时,如果父类引用调用的方法在父类中有(子类继承于父类)那就直接用子类的,如果父类中没有(说明是子类独有的)那么父类引用就不能用。
5.隐藏
与重写类似,重写是子类覆盖父类的**对象方法**。隐藏则是子类覆盖父类的类方法(加了static关键字的方法)。
6. super关键字
实例化一个对象时,会调用该对象所在的类的默认无参构造方法。如果该对象所在的类有父类,那么会先调用父类的无参构造方法,再调用自身的无参构造方法。
若子类与父类都创建了带相同参数的构造方法,并且子类new的对象也有该类型参数。如果没有使用super关键字,那么子类在执行的时候依然会先调用父类的无参构造方法。使用super关键字可以显式调用父类带参的构造方法,可以调用父类属性,调用父类方法。
7. Object类
在Java中所有的类都直接或间接继承了java.lang.Object类,Object类是所有类的父类,是java类层中的最高层类。
在Object类中主要包括clone()、finalize()、equals()、toString()等方法,其中常用的的两个方法为equals()和toString()。由于所有类都是Object类的子类,所以任何类都可以重写Object类中的方法。
①getClass()方法:返回对象执行时的Class实例,然后使用此实例调用getName()方法可以取得类的名称。可以将getClass()方法和toString()方法联合使用。
getClass().getName();//使用格式
②toString()方法:将一个对象返回为字符串形式,会返回一个String实例。在实际应用中通常重写toString()方法,为对象提供一个特定的输出模式。当这个类转换为字符串或与字符串连接时,将自动调用重写的toString()方法。
③finalize()方法:当一个对象没有任何指向时,它就满足垃圾回收的条件。当它被垃圾回收时,它的finalize()方法就会被调用(当垃圾堆积足够多(接近1000000)时)。finalize()方法是由虚拟机JVM调用的。
④equals()方法:用于判断两个对象的内容是否相同。”“运算符与equals()方法的区别在于:”“比较的是两个对象的引用是否相同(或两个引用是否指向同一个对象),equals()比较的时两个对象的实际内容。
8. final()方法
关键字final()在修饰类、方法、基本类型变量、引用时有不同的含义。
①final修饰变量
final关键字可用于变量声明,一旦该变量被设定就不能再改变该变量的值。通常由final定义的变量都是常量,若在程序中再次对定义为final的常量赋值,编译器将不会接受。
被定义为final的常量定义时需要使用大写字母命名,并且中间使用下划线进行连接。
②final修饰对象引用
一旦一个对象引用被final修饰,它只能恒定指向一个对象,无法将其改变以指向另一个对象。由于对象本身的值是可以改变的,为了使一个常量真正做到不可更改,可以将常量声明为static final。一个既是static又是final的字段只占据一段不能改变的存储空间。
③final修饰方法
定义为final的方法不能被重写。将方法定义为final类型,可以防止子类修改该类的定义与实现方式,同时定义为final的方法的执行效率要高于非final方法。若一个父类的某个方法被设置成为private修饰符,子类将无法访问该方法,自然也无法覆盖(即重写)该方法。也就是说,一个定义为private的方法隐式地被指定为final类型,因此无须将一个定义为private的方法再定义为final类型。
④final修饰类
定义为final的类不能被继承。如果希望一个类不被任何类继承,并且不允许其他人对这个类进行任何改动,可以将这个类设置为final形式。
若某个类被设置为final形式,则类中的所有方法都被隐式设置为final形式,但是final类中的成员变量可以被定义为final或非final形式。
9.抽象类
使用abstract关键字定义的类称为抽象类,而使用这个关键字定义的方法称为抽象方法。
抽象方法没有方法体,除非它被重写,而承载这个抽象方法的抽象类必须被继承。
反过来说,只要类中有一个抽象方法,那么该方法所在的类就会被标记为抽象类。继承抽象类的所有子类都需要将抽象类中的抽象方法进行覆盖(重写)。
由此可知在多态的机制中(父类引用指向子类对象),可以将父类修改为抽象类。则每个子类都需要重写其中的抽象方法,那么程序中将会出现太多的冗余代码。同时这样的父类局限性也非常大,因为不需要某个抽象方法的子类也必须重写该抽象方法,为了应对这种问题于是引进了接口的概念。
抽象类和接口的区别
- 区别1:子类只能继承一个抽象类,不能继承多个。子类可以实现多个接口。
- 区别2:抽象类可以定义public,protected,package,private,静态和非静态属性,final和非final属性。但是接口中声明的属性,只能是public、静态、final的,即便没有显式的声明。
10.内部类
①成员内部类(非静态内部类)
在一个类中使用内部类,可以在内部类中直接存取其所在类的私有成员变量。
注:内部类对象对以来与外部类对象,除非已经存在一个外部类对象,否则类中不会出现内部类对象。即在实例化内部类对象时,必须在new操作符之前提供一个外部类的引用。
语法: new 外部类().new 内部类()。
e . g .
OuterClass out=new OuterClass();//实例化一个外部类对象
OuterClass.innerClass in=out.new innerClass();//实例化一个内部类对象
②静态内部类
在内部类前添加修饰符static,这个内部类就变为静态内部类。静态内部类的最大特点就是不可以使用外部类的非静态成员(但可以访问外部类的私有静态成员)。如果创建静态内部类的对象,不需要其外部类的对象。不能从静态内部类的对象中访问非静态外部类的对象。
语法:new 外部类.静态内部类();
e . g .
//实例化静态内部类
Hero.EnemyCrystal crystal = new Hero.EnemyCrystal();
crystal.checkIfVictory();
③匿名内部类
匿名类指的是在声明一个类的同时将其实例化,使得代码更加简洁精炼。
有的时候,为了快速使用,直接实例化一个抽象类,并“当场”实现其抽象方法。既然实现了抽象方法,那么就是一个新的类,只是这个类,没有命名。这样的类,叫做匿名类
④本地类
本地类可以理解为有名字的匿名类。
内部类与匿名类不一样的是,内部类必须声明在成员的位置,即与属性和方法平等的位置。
本地类和匿名类一样,直接声明在代码块里面,可以是主方法,for循环里等等地方。
注:在匿名类中使用外部的局部变量,外部的局部变量必须修饰为“final”。但在jdk8中,已经不需要强制修饰final了,如果没有加final编译器不会报错,因为编译器自动加上了final。
11.默认方法
默认方法是JDK8新特性,指的是接口也可以提供具体方法了,而不像以前,只能提供抽象方法。
假设没有默认方法这种机制,那么如果要为Mortal增加一个新的方法revive,那么所有实现了Mortal接口的类,都需要做改动。但是引入了默认方法后,原来的类,不需要做任何改动,并且还能得到这个默认方法。通过这种手段,就能够很好的扩展新的类,并且做到不影响原来的类
如果一个类同时实现两个接口中的同一种默认方法(方法名一样,方法体不一样),那么必须在该类中重写该默认方法,避免不知道该调用哪个接口中的默认方法。