多态
-
概念:一类事物的多种形态
父类 变量名=new 子类(); 走子类-重写-的成员方法,但是变量还是父类的 接口 变量名=new 子类();
-
特点:左边是父类,右边是任意子类;提高代码的扩展性
编译看左边,运行看右边(父类没有子类特有的方法,不能被调用)
-
使用场景:在工作中更好的合作,在参数传递的时候,参数写父类,以后修改代码更加方便,可以传入任何一个子类
-
引用类型的转换:
1.向上转型:子类转换为父类,也就是多态
父类 变量名=new 子类();
2.向下转型:父类转成子类(强制转换)
子类 变量名=(子类) 父类变量;
3.代码演示:
Teacher t=new Student(); t.eat(); Student s=(Student) t; s.study();
-
instance of关键字:在向下转型前先判断
父类对象 instanceof 子类 --> 返回值 boolean
代码演示:
public interface USB{} //接口 public class Mouse implements USB{} //接口实现类 public class KeyBoard implements USB{} //接口实现类 public void use(USB u) { //传入接口 u.connect(); if (u instanceof Mouse) { Mouse mouse = (Mouse) u; mouse.click(); //Mouse自己的方法 } else if (u instanceof KeyBoard) { KeyBoard key=(KeyBoard) u; key.type(); //KeyBoard自己的方法 } u.disconnect(); }
内部类
-
概念:一个类定义在另一个类里面
外部类{ 内部类{} }
-
使用场景:一个事物内部还有一个事物,而且内部事物不能脱离外部事物
-
内部类
-
成员内部类(在类中,方法外)
-
使用: 1.创建外部类对象 2.通过外部类创建内部类对象
Body b=new Body(); Body.Heart h=Body.new Heart();
-
特点:可以直接使用外部类的成员, 但是很容易被替代,用的不多
-
编译:外部类$内部类.class
class Body { private int weight=30; class Heart{ private int weight=20; public void test(){ private itn weight=10; System.out.println(weight); //10 System.out.println(this.weight); //10 System.out.println(Body.this.weight); //10 } } }
-
-
静态成员内部类
-
在成员内部类前面添加static修饰
-
直接创建静态内部类
Body.heart a=new Body.heart(); //不常用
-
-
局部内部类(在方法里面定义的类)
- 使用:在定义内部类的下方创建对象去使用,只能在本方法里面使用
- 编译:外部类名$编号 内部类
-
匿名内部类
-
没有名字的类
new 父类/接口(){ 重写方法; } Student s=new Studnet(){ @Override public void 方法名(){ } }
-
特点:简化代码
public interface Eat{}
Eat a=new Eat() { @Override public void eat() { System.out.println("匿名内部类吃饭"); } }; a.eat(); //只会调用一次 new Eat(){ @Override public void eat() { System.out.println("匿名内部类又去吃饭了"); } }.eat();
-
使用场景:方法参数是接口时 常规:传入接口的实现类对象
-
-
思考题:
1.内部类如何访问外部类成员变量
单例
-
单例设计模式:让一个类只有一个对象
- 饿汉式单例(推荐)
- 懒汉式单例
-
实现步骤:
-
将构造器私有,别人不能使用
-
使用成员变量保存创建的对象
private static final 类名 变量名=new 类名
-
提供公共的访问方式(使用static关键字,用类名调用)
public static 类名 方法名(){ return 变量名; }
-
枚举
-
作用:列举某个类型(固定)的所有值
-
格式:
enum 枚举名{ 成员变量名1,成员变量名2,成员变量名3; } //成员变量名也叫枚举项 //使用 枚举名.枚举项
-
特点:保证数据不非法
思考:
1.使用接口作为方法的参数,可以传递实现了这个接口的所有类,那么父类和子类呢?在写代码的时候怎么也理解不了方法参数的明明是接口,可是这个接口的实现类却可以传递进去,实验了之后发现父类和子类也同样适用.其实这就是多态
其实多态不仅仅是说引用父类去创建一个子类,可以把子类的数据类型看做父类,所以当方法形参的数据类型为父类的时候,子类可以被传递进去
//父类
public abstract class Person {
private int age;
private String name;
public abstract void eat();
...省略构造器和get/set....
}
//接口
public interface Play {
public abstract void playBasketball();
}
//继承父类的学生类
public class Student extends Person{
@Override
public void eat() {
System.out.println("学生在吃学生餐");
}
public void study(){
System.out.println("学生要学习");
}
}
//继承父类实现接口类
class SuperStudent extends Student implements Play{
@Override
public void playBasketball() {
System.out.println("年龄为"+getAge()+"岁的"+getName()+"的学生在打篮球");
}
}
//测试
public class Test {
public static void main(String[] args) {
Teacher t1 = new Teacher();
superTeacher t2 = new superTeacher(35,"大姚");
Student s1 = new Student();
SuperStudent s2 = new SuperStudent(21,"王中王");
goSport(t2);
goSport(s2);
test(t1);
test(t2);
test(s1);
test(s2);
}
//有继承了Person类的子类都可以传递进去
public static void test(Person person) {
person.eat();
}
//有继承了接口的实现类都可以传递进去
public static void goSport(Play s){
s.playBasketball();
}
}