类的继承
创建子类语法:
修饰符 class 子类名 extends 父类名{
}
匿名子类语法:
直接实例化,过程中通过匿名类 继承父类,在实例化过程中将子类匿名
<父类类名> 实例名 = new 父类名() {
匿名类代码逻辑....
}
自定义类默认继承了Object类:
自定义类默认隐藏式继承了Object类
class Cat {
...
}
等价于如下
class Cat extends Object{
.........
}
类的继承特性:
1、没指定继承哪个父类,默认继承Object
2、在Java中Object类是所有类的父类
3、子类继承父类时,不能继承父类的构造方法【这一点不如Python】
4、父类叫做基类,子类叫做派生类
5、满足条件is a
6、一个类只能继承一个直接父类
7、类继承具有传递性。
理解视图举例
代码举例:水果~苹果
父类:水果
package com.zmd.study.exten; public class Fruit { /** * 水果的重量属性 */ private double weight ; public double getWeight() { return weight; } public void setWeight(double weight) { this.weight = weight; } }
子类:苹果类
package com.zmd.study.exten; public class Apple extends Fruit{ public String color ; public String getColor() { return color; } public void setColor(String color) { this.color = color; } }
测试类输出:
public class Test { public static void main(String[] args) { Apple apple = new Apple(); apple.setWeight(0.3); System.out.println("苹果重量:" + apple.getWeight()); } } /** 输出: 苹果重量:0.3 */
重写父类方法
---子类的方法名、参数列表、修饰符一致
---子类的返回类型一致或父类方法返回类型的子类型:
例如:String 是Object的子类型
int 是 Double的子类型
super
注意事项:
1、super.方法/变量。直接访问父类的资源
2、如果不写,默认为访问本类中资源即隐含了this.
3、如果子类重写父类的方法体中,有调用被重写的方法,则只能使用super
4、访问父类中的实例变量可以是this. 也可以是super. 但是范围子类独有的实例变量/方法 只能用this
5、super(); super([参数列表])完成对父类构造方法赋值
重写的方法无返回值测试
水果父类
package com.zmd.study.exten; /** * @ClassName Fruit * @projectName: object1 * @author: Zhangmingda * @description: XXX * date: 2021/3/28. */ public class Fruit { /** * 水果的重量属性 */ private double weight ; public double getWeight() { return weight; } public void setWeight(double weight) { this.weight = weight; } public void showInfo(){ //被子类重写的方法 System.out.println("我是水果,我的重量是:" + weight ); } }
子类
package com.zmd.study.exten; import java.sql.SQLOutput; /** * @ClassName Apple * @projectName: object1 * @author: Zhangmingda * @description: XXX * date: 2021/3/28. */ public class Apple extends Fruit{ public String color ; public String getColor() { return color; } public void setColor(String color) { this.color = color; } public void showInfo(){ //调用父类中的方法用super super.showInfo(); System.out.println("我是苹果,我的重量是:" + this.getWeight()); } }
测试类&执行效果
import com.zmd.study.exten.Apple; public class Test { public static void main(String[] args) { Apple apple = new Apple(); apple.setWeight(0.2); apple.showInfo(); } } /** 输出: 我是水果,我的重量是:0.2 我是苹果,我的重量是:0.2 */
子类和父类的属性名相同
如果在子类中定义了与父类中同名的变量,那么子类中会隐藏父类的变量。但不是完全覆盖。在子类初始化的时候依然会为父类变量分配内存空间。通过父类中public属性的方法仍然可以访问父类的对应属性。
如下示例:水果父类中名字 苹果类中名字重复
package com.zmd.study.exten; public class Fruit { /** * 水果的重量属性 */ private double weight ; /** * 名字 */ private String name = "水果"; public double getWeight() { return weight; } public void setWeight(double weight) { this.weight = weight; } public void showInfo(){ //被子类重写的方法 System.out.println("我是"+ name +",我的重量是:" + weight ); } }
苹果类
package com.zmd.study.exten; import java.sql.SQLOutput; /** * @ClassName Apple * @projectName: object1 * @author: Zhangmingda * @description: XXX * date: 2021/3/28. */ public class Apple extends Fruit{ public String name = "苹果"; public String color ; public String getColor() { return color; } public void setColor(String color) { this.color = color; } public void showInfo(){ //调用父类中的方法用super super.showInfo(); System.out.println("我是"+ name +",我的重量是:" + this.getWeight()); } }
测试类
public class Test { public static void main(String[] args) { Apple apple = new Apple(); apple.setWeight(0.2); apple.showInfo(); } }
输出:
我是水果,我的重量是:0.2
我是苹果,我的重量是:0.2
父类中含有构造方法
父类中只有一个有参构造。则子类构造方法必须给父类构造方法参数传值:
即有参构造方法会覆盖无参构造方法,当不存在无参构造方法不存在的时候,java自动会运行一个空的无参构造方法。
如果子类构造方法不想给父类调用父类有参构造:父类必须含有无参构造方法。
语法:
public 类名([参数列表]){
完成对子类成员变量赋值;
super(参数); //完成对父类构造方法赋值
}
水果(父)类举例
package com.zmd.study.exten; /** * @ClassName Fruit * @projectName: object1 * @author: Zhangmingda * @description: XXX * date: 2021/3/28. */ public class Fruit { /** * 水果的重量属性 */ private double weight ; /** * 名字 */ private String name = "水果"; /** * 父类无参构造方法 */ public Fruit() { } /** * 父类有参构造方法 * @param weight * @param name */ public Fruit(double weight, String name) { this.weight = weight; this.name = name; } public void showInfo(){ //被子类重写的方法 System.out.println("我是"+ name +",我的重量是:" + weight ); } }
苹果类~子类
package com.zmd.study.exten; import java.sql.SQLOutput; /** * @ClassName Apple * @projectName: object1 * @author: Zhangmingda * @description: XXX * date: 2021/3/28. */ public class Apple extends Fruit{ public String name = "苹果"; public String color ; /** * 子类无参构造 */ public Apple() { } /** * 子类有参构造 * @param weight * @param name */ public Apple(int weight, String name) { super(weight,name); } }
对比说明
实例化子类过程中发生了什么?
1、子类名obj = new 子类();
2、执行了父类对应构造super()
如果不手动执行super(参数),而子类构造方法中直接执行对父类的成员变量赋值,则默认会执行super()父类无参构造一次
则:需注意,构造方法无参的无用也要写上避免出现错误
所有类的祖类(默认父类)都是Object
instanceof 判断前面的实例是不是后面类的实现
public class Test { public static void main(String[] args) { Apple apple = new Apple(); System.out.println(apple instanceof Object); } /** 输出:true */
多态特性
Javad 引用变量有两个类型,一个是编译时类型,一个是运行时类型。
编译时类型由声明该变量时使用的类型决定。
运行时类型由实际赋给该变量的对象决定,如果编译时类型和运行时类型不一致,就可能出现所谓的“多态”
通俗理解:用父类声明变量,用子类来实例化
语法:
父类类名 引用名称 = new 子类类名();
注意,引用名称.只能访问父类的实例属性和实例方法,如果子类重写了父类的方法,则优先访问子类的方法。
示例:动物类、 下属 猫类、狗类
package com.zmd.study.exten; public class Animal { public void say(){ System.out.println("本动物要叫了...."); } }
package com.zmd.study.exten; public class Dog extends Animal{ public void say(){ System.out.println("小狗汪汪汪~~~!!!"); } }
package com.zmd.study.exten; public class Cat extends Animal{ public void say(){ System.out.println("本小猫 喵喵喵~~~!!!"); } }
测试类
//import org.omg.Messaging.SYNC_WITH_TRANSPORT; import com.zmd.study.exten.Animal; import com.zmd.study.exten.Cat; import com.zmd.study.exten.Dog; public class Test { public static void main(String[] args) { Animal dog = new Dog(); Animal cat = new Cat(); dog.say(); cat.say(); } /** 小狗汪汪汪~~~!!! 本小猫 喵喵喵~~~!!! */
使用子类特有的方法报错:比如小狗比动物多了生气的方法
package com.zmd.study.exten; public class Dog extends Animal{ public void say(){ System.out.println("小狗汪汪汪~~~!!!"); } public void angry(){ System.out.println("小狗生气了~要咬人"); } }
测试
import com.zmd.study.exten.Animal; import com.zmd.study.exten.Cat; import com.zmd.study.exten.Dog; public class Test { public static void main(String[] args) { Animal dog = new Dog(); dog.angry();//这里直接报语法错误:找不到符号,因为父类中没有 }
强制类型转换
语法:子类类型 引用名称 = (子类类型) 父类对象
注意:需要保证当前运行时的对象,一定是我们要转换对象的实例或者子类的实例。
import com.zmd.study.exten.Animal; import com.zmd.study.exten.Cat; import com.zmd.study.exten.Dog; public class Test { public static void main(String[] args) { Animal dog = new Dog(); Dog dog1 = (Dog)dog; dog1.angry(); } /** 小狗生气了~要咬人 */
instanceOf 关键字
判断实例是不是后面类或者子类实例化的一个对象
语法:<引用类型的变量> instanceOf <类>
返回布尔值true/false
示例
System.out.println(dog instanceof Animal); System.out.println(dog instanceof Cat); /** true false */