1.继承
当一个或者多个对象有公共的特性是我们可以将他们共同的特性定义成一个实体,让那些多个对象去继承他的,这样可以减少代码的冗余。比如狗和猫它们都共同具有吃和工作的共性,所以我们就可以定义一个动物类,让动物类拥有吃和工作的方法,再让猫和狗继承动物类,这样猫和狗里面就有了吃和工作的方法。如果猫中吃的方法需要进一步完善那我们可以进行重写。如果猫还可以游泳那就再写一个游泳的方法。
public abstract class Animal {
abstract void eat();
}
class Dog extends Animal{
void eat(){
System.out.println("吃肉");
}
public void work(){
System.out.println("看家");
}
}
class Cat extends Animal{
void eat() {
System.out.println("吃鱼");
}
public void work(){
System.out.println("抓老鼠");
}
}
public class Test {
public static void main(String[] args) {
show(new Cat());
show(new Dog());
Animal a=new Cat();
a.eat();
Dog d=new Dog();
d.work();
}
public static void show(Animal a) {
a.eat();
if (a instanceof Cat) {//注意instanceof
Cat c = (Cat) a;
c.work();
} else if (a instanceof Dog) {
Dog c = (Dog) a;
c.work();
}
}
}
结果:
吃鱼
抓老鼠
吃肉
看家
吃鱼
看家
instanceof
用法:
result = object instanceof class
说明:
如果 object 是 class 的一个实例,则 instanceof 运算符返回 true。如果 object 不是指定类的一个实例,或者 object 是 null,则返回 false。
但是instanceof在Java的编译状态和运行状态是有区别的:
在编译状态中,class可以是object对象的父类,自身类,子类。在这三种情况下Java编译时不会报错。
在运行转态中,class可以是object对象的父类,自身类,不能是子类。在前两种情况下result的结果为true,最后一种为false。但是class为子类时编译不会报错。运行结果为false。
2.接口
接口并不是类,编写接口的方式和类很相似,但是它们属于不同的概念。类描述对象的属性和方法。接口则包含类要实现的方法。
除非实现接口的类是抽象类,否则该类要定义接口中的所有方法。
接口无法被实例化,但是可以被实现。一个实现接口的类,必须实现接口内所描述的所有方法,否则就必须声明为抽象类。另外,在 Java 中,接口类型可用来声明一个变量,他们可以成为一个空指针,或是被绑定在一个以此接口实现的对象。
public class MammalInt implements Animal{
public void eat(){
System.out.println("Mammal eats");
}
public void travel(){
System.out.println("Mammal travels");
}
public int noOfLegs(){
return 0;
}
public static void main(String args[]){
MammalInt m = new MammalInt();
m.eat();
m.travel();
}
}
3.多态
多态的优点
- 消除类型之间的耦合关系(耦合关系是指某两个事物之间如果存在一种相互作用、相互影响的关系,那么这种关系就称”耦合关系“。)
- 可替换性
- 可扩充性
- 接口性
- 灵活性
- 简化性#### 多态的优点
多态存在的三个必要条件
- 继承
- 重写
- 父类引用指向子类对象
public class Test {
public static void main(String[] args) {
show(new Cat()); // 以 Cat 对象调用 show 方法
show(new Dog()); // 以 Dog 对象调用 show 方法
Animal a = new Cat(); // 向上转型
a.eat(); // 调用的是 Cat 的 eat
Cat c = (Cat)a; // 向下转型
c.work(); // 调用的是 Cat 的 work
}
public static void show(Animal a) {
a.eat();
// 类型判断
if (a instanceof Cat) { // 猫做的事情
Cat c = (Cat)a;
c.work();
} else if (a instanceof Dog) { // 狗做的事情
Dog c = (Dog)a;
c.work();
}
}
}
abstract class Animal {
abstract void eat();
}
class Cat extends Animal {
public void eat() {
System.out.println("吃鱼");
}
public void work() {
System.out.println("抓老鼠");
}
}
class Dog extends Animal {
public void eat() {
System.out.println("吃骨头");
}
public void work() {
System.out.println("看家");
}
}
结果:
吃鱼
抓老鼠
吃骨头
看家
吃鱼
抓老鼠
super的用法
1.普通的直接引用
super 可以引用父类的属性(但不能说super指向当前对象的父类,这样的说法是不严谨的)。
2.子类中的成员变量或方法与父类中的成员变量或方法同名
class Animal {
public int a=10;
void print(){
System.out.println("I'm Animal");
}
}
class Dog extends Animal{
void print(){
super.print();
System.out.println("I'm Dog");
System.out.println(super.a);
}
}
public class Test {
public static void main(String[] args) {
Animal dog=new Dog();
dog.print();
}
}
结果:
I’m Animal
I’m Dog
10
3.引用构造函数
-
super(参数):调用父类中的某一个构造函数(应该为构造函数中的第一条语句)。
-
this(参数):调用本类中另一种形式的构造函数(应该为构造函数中的第一条语句)。
package com.company.animal;
class Animal {
public static void prt(String s) {
System.out.println(s);
}
Animal(){
prt("父类无参构造方法");
}
Animal(String name){
prt("父类有参构造方法"+name);
}
}
class Dog extends Animal{
Dog(){
super();
prt("子类无参构造方法");
}
Dog(String name){
super(name);
prt("子类有参构造方法"+name);
}
Dog(String name,int age){
this(name);
prt("子类相同形参的构造函数"+age);
}
}
public class Test {
public static void main(String[] args) {
Animal dog=new Dog();
dog=new Dog("晨光");
dog=new Dog("狗晨光",1);
}
}
结果:
父类无参构造方法
子类无参构造方法
父类有参构造方法晨光
子类有参构造方法晨光
父类有参构造方法狗晨光
子类有参构造方法狗晨光
子类相同形参的构造函数1
从本例可以看到,可以用 super 和 this 分别调用父类的构造方法和本类中其他形式的构造方法。
4.this的使用方法
- 普通的直接引用
- 形参与成员名字重名,用 this 来区分
- 引用构造函数
super与this的异同
- super(参数):调用基类中的某一个构造函数(应该为构造函数中的第一条语句)
- this(参数):调用本类中另一种形成的构造函数(应该为构造函数中的第一条语句)
- super: 它引用当前对象的直接父类中的成员(用来访问直接父类中被隐藏的父类中成员数据或函数,基类与派生类中有相同成员定义时如:super.变量名
super.成员函数据名(实参) - this:它代表当前对象名(在程序中易产生二义性之处,应使用 this 来指明当前对象;如果函数的形参与类中的成员数据同名,这时需用
this 来指明成员变量名) - 调用super()必须写在子类构造方法的第一行,否则编译不通过。每个子类构造方法的第一条语句,都是隐含地调用
super(),如果父类没有这种形式的构造函数,那么在编译的时候就会报错。 - super() 和 this() 类似,区别是,super() 从子类中调用父类的构造方法,this() 在同一类内调用其它方法。
- super() 和 this() 均需放在构造方法内第一行。
- 尽管可以用this调用一个构造器,但却不能调用两个。
- this 和 super 不能同时出现在一个构造函数里面,因为this必然会调用其它的构造函数,其它的构造函数必然也会有 super语句的存在,所以在同一个构造函数里面有相同的语句,就失去了语句的意义,编译器也不会通过。
- this() 和 super() 都指的是对象,所以,均不可以在 static 环境中使用。包括:static 变量,static
方法,static 语句块。 - 从本质上讲,this 是一个指向本对象的指针, 然而 super 是一个 Java 关键字。