什么是多态?
:指的是一个对象的多种形态,使用多态前提是要有继承和接口的实现
- 1.方法的重载和重写就是一种多态
- 2.子类对象的多态性
Pet p1=new Dog(“泰迪”, “小迪”); - 1).分类的引用指向的是子类的实例
- 2).在执行时,调用的是子类的方法,在编译时,调用的是父类的方法
- 3).编译时,看左边,运行时,看右边
举例说明:
首先简单的建一个宠物类,有昵称和健康值两个属性。
//宠物类
public class Pet {
protected String name="无";//昵称
protected int health=100;//健康值
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getHealth() {
return health;
}
public void setHealth(int health) {
this.health = health;
}
public Pet(String name, int health) {
super();
this.name = name;
this.health = health;
}
public Pet(String name) {
super();
this.name = name;
}
public Pet(int health) {
super();
this.health = health;
}
public Pet() {
super();
}
//输出宠物信息
public void info(){
System.out.println("名字叫:"+name+",健康值是:"+health);
}
//宠物吃食
public void eat(){
System.out.println("宠物吃饭");
}
}
然后建一个狗类,狗是宠物,所以会继承宠物类。代码如下:
(有自己的品种属性,重写了吃饭方法,输出方法,加了一个睡觉方法)
public class Dog extends Pet{
private String strain;//品种
public String getStrain() {
return strain;
}
public void setStrain(String strain) {
this.strain = strain;
}
public Dog (String strain,String name){
super (name);
this.strain=strain;
}
//重写吃饭方法
public void eat(){
super.health=super.health+3;
System.out.println("狗狗吃饱了,健康值加3");
}
//重写输出方法
public void info(){
super.info();
System.out.println("我是一只:"+this.strain);
}
//睡觉
public void sleep(){
System.out.println("狗狗在呼呼大睡");
}
}
现在用Test测试一下:
public class Test {
public static void main(String[] args) {
//创建宠物类对象
Pet p = new Pet("旺旺");
p.info();
p.eat();
//创建狗类对象
Dog dog = new Dog("金毛","小金");
dog.info();
//调用吃饭方法
m.feed(dog);
m.feed(pe);
//子类对象的多态性
Pet p1=new Dog("泰迪","小迪");//向上转型
p1.info();
//编译期间,程序会把p1当成父类对象,而父类没有sleep()方法
//p1.sleep();这里会有错误,因为Pet类里没有睡觉方法。
可以看到这里,可以用Pet new一个Dog,不报错误,这就是
向上转型
,“上”可以理解为“父类”。一个子类对象可以转型为父类对象。这就叫子类对象的多态性。(自我感觉跟重写类似)
思考:如果现在就想用p1调用子类独有的方法,怎么做?
答:可以强制类型转换,即
向下转型
,怎么用:(在p1前加括号,Dog)跟C语言强制类型转换一样,这样就可以调用Dog类里的sleep方法了。
Dog dog1=(Dog)p1;//向下转型
dog1.sleep();
还有一个问题,在建另一个企鹅(Penguin)类:
public class Penguin extends Pet {
private String sex;//性别
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public Penguin(String sex,String name) {
super(name);
this.sex = sex;
}
public Penguin() {
super();
}
//重写吃饭方法
public void eat(){
super.health=super.health+5;
System.out.println("企鹅吃饱了,健康值加5");
}
//重写输出方法
public void info(){
super.info();
System.out.println("我的性别是:"+this.sex);
}
//游泳
public void swimming(){
System.out.println("企鹅游泳 ");
}
}
发现,同样是继承的Pet类,里边有独有方法swimming.
- 在测试时,在 Test类里
Dog dog1=(Dog)p1;
dog1.sleep();
两句下面再加两行:
Penguin pe1=(Penguin) p1;
pe1.swimming();
此时,编译Test是没问题的,但是运行会抛出异常ClassCastException
。
这是因为,编译时,看左边,运行时,看右边。
- 编译左边Penguin pe1是没问题的。但是运行时,p1已经转成了dog,把dog转成penguin是有问题的。
如何解决?用instanceof
方法处理一下就可以,语法如下:
此时Test类运行正常。
final关键字
:代表最终的意思
可以修饰什么?
1.修饰类
2.方法
3.成员变量
4.局部变量
修饰类,这个类有什么特点?
1.这个类不能被继承,但是可以继承别的类
2.final修饰方法,这个方法就是一个最终方法,不能被重写。
测试一下:
(简单一个类,用final定义method() 方法)
public class MyClass {
public final void method(){
System.out.println("这是一个最终方法");
}
}
接着用MyClass1类继承MyClass,在子类MyClass1里重写method() 方法,
public class MyClass1 extends MyClass {
public void method(){
}
}
报错:
3.final修饰成员变量,成员变量的值不可改变
1)成员变量就没有默认值了
2)如果使用final关键字,那么要直接对成员变量进行赋值
例如:
(里面的date)
public class Order {
private int oid;
private String name;
private final String date="2020-1-8";
public int getOid() {
return oid;
}
public void setOid(int oid) {
this.oid = oid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDate() {
return date;
}
public Order(int oid, String name) {
super();
this.oid = oid;
this.name = name;
}
public Order() {
super();
}
@Override
public String toString() {
return "Order [oid=" + oid + ", name=" + name + ", date=" + date + "]";
}
}
输出正常。
4.final修饰局部变量,值不能改变
final int num=10;
// num=12;
System.out.println(num);
注释部分为错误代码,不能再赋值。
下面这个是可以的:
(不要看混了)
final int num1;
num1=20;
System.out.println(num1);
总结一下:
1.final修饰的类不能被继承。提高安全性,提高程序的可读性。
2.final修饰的方法不能被子类重写。
3.final修饰的属性为常量。一旦初始化后,不可再被赋值。习惯上,常量用大写字符表示。
static关键字
:静态的,可以修饰属性、方法、代码块。
1.static 修饰属性:
1)由类创建的所有对象,都共享这个属性
2)如果其中的一个对象属性值发生了改变,会导致其他对象属性值跟着改变
3)类变量随着类的加载而加载,独一份
4)静态变量可以直接通过“类名.类变量”的方式调用
5)类变量存在静态域中
6)类变量的加载要早于对象
2.static 修饰方法(类方法)
1)随着类加载而加载
2)可以直接通过“类名.方法名”的方式调用
3)内部可以调用静态方法或者是静态属性,不能调用非静态方法和属性,非静态方法可以调用静态变量和静态方法
例子:
- 创建一个SportsMan对象(名字,年龄,国际三个属性,其中
nation
用了static
关键字,有一个static
修饰的show1()
方法(静态方法)。)
public class SportsMan {
//实例对象 ,随着对象的创建而加载
private String name;
private int age;
static String nation;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public SportsMan(String name, int age) {
super();
this.name = name;
this.age = age;
}
public SportsMan() {
super();
}
public String getNation() {
return nation;
}
public String setNation(String nation) {
return nation;
}
@Override
public String toString() {
return "SportsMan [name=" + name + ", age=" + age +", nation=" + nation+ "]";
}
public void show(){
System.out.println("这是一个普通方法");
}
public static void show1(){
// System.out.println("age:"this.age);
System.out.println("这是一个静态方法");
}
}
Test类测试一下:
public class TestSportsMan {
public static void main(String[] args) {
SportsMan.nation="11";
SportsMan s1=new SportsMan("张三",20);
s1.setNation("中国");
s1.show();
System.out.println(s1);
SportsMan.show1();
SportsMan s2=new SportsMan("李四",67);
System.out.println(s2);
}
}
运行结果如下:
直接通过“类名.方法名”的方式调用。 中间的setNation
没有排上用场,国籍并没有更改。
*注意:静态方法不能使用this和super关键字
3.static可以修饰代码块
(暂时没有用到,所以只了解即可。)