一、内部类
分类:
成员内部类(常用)
静态内部类(常用)
接口内部类
局部内部类
匿名内部类(常用)
成员内部类,静态内部类,局部内部类:
public class Outter {
String str1 = "成员变量";
class 成员内部类{//类似于成员变量
}
static String str= "静态变量";
static class 静态内部类{//类似于静态变量
}
public void method(){
String str3 = "局部变量";
class 局部内部类{//类似于局部变量
}
}
}
接口内部类:就是接口中的类
匿名内部类:就是创建创建接口或抽象类对象时,创建的没有名字的类。(接口和抽象类不能直接创建对象)
内部类的使用场景:
A类的对象只在B类中使用,并且A类使用到了B类所有的成员属性,就可以将A类变作为B类的成员内部类
A类的对象只在B类中使用,并且A类使用到了B类的静态属性,就可以将A类变作为B类的静态内部类
抽象类的子类对象只使用了一次,就可以使用匿名内部类
接口的实现类对象只使用了一次,就可以使用匿名内部类
1、成员内部类
类似于成员变量
重点:成员内部类可以调用外部类的所有属性
创建对象:Inner inner = new Outter().new Inner();
----(创建成员内部类的对象,先要创建外部类对象)
----Outter.this.str1//如果外部类属性名和内部类属性名冲突了,这种写法是指定调用外部类的属性
2、静态内部类
类似于静态变量
重点:静态内部类不可以调用外部类的成员属性,只能调用外部类的静态属性
静态内部类为什么不可以调用外部类的成员属性?
创建静态内部类对象,不会创建外部类对象,所以外部类的成员属性不会在内存中出现,所以不能调用
创建对象:Inner inner = new Outter.Inner();
----(创建静态内部类对象,不会创建外部类对象)
3、接口内部类
类似于静态内部类
重点:接口内部类中可以调用接口的静态常量
接口内部类默认使用public static 修饰类
4、局部内部类
类似于局部变量
重点:
1.不能使用访问修饰符修饰局部内部类
2.局部内部类调用外部类方法中的局部变量,在JDK1.8开始该变量会自动使用final修饰,变成常量
----原因:内部类对象可能被传送到外界,该方法结束后,i作为常量存储在常量池中,保证了内部类对象在外界正常使用到常量i
通过调用外部类的方法来调用局部内部类
5、匿名内部类
一个没有名字的类,用于创建抽象类对象或接口类对象
A.java
public abstract class A {
public abstract void method();
}
I1.java
public interface I1 {
public void method();
}
Test.java
public class Test {
public static void main(String[] args) {
A a = new A(){ //匿名内部类,实现抽象类
@Override
public void method() {
System.out.println("xxx");
}
};
a.method();
I1 i1 = new I1(){ //匿名内部类,实现接口
@Override
public void method() {
System.out.println("yyy");
}};
i1.method();
}
}
实现步骤:
1.创建匿名子类,继承抽象类或接口类,重写method方法
2.创建匿名子类对象
3.赋值给父类的引用(多态)
二、对象转型
1.向上转型:子类类型 转 父类类型
可以调用父类的非私有化成员变量
可以调用父类的非私有化的成员方法
可以调用子类重写父类的成员方法
扩展:向上转型其实就是多态
多态的优点:符合OCP原则的开发,需求更改时,项目的可维护性高
多态的缺点:不能调用子类独有的成员变量和成员方法
2.向下转型:父类类型 转 子类类型
注意:向下转型是不安全的
1、向上转型
子类类型转父类类型
Father f = new Son();
----若父类方法被重写,则调用被重写的方法
----父子类的成员变量重名时,依旧调用父类成员变量
----父子类有相同名的静态变量,依旧是调用父类的静态变量
----父子类有相同名的静态方法,依旧是调用父类的静态方法
--------未标粗的3点也证实多态不能调用子类独有的成员变量和成员方法
2、向下转型
父类类型 转 子类类型
Son s = (Son)new Father();
----要强制类型转换
注意:
1.向下转型是不安全的
2.向上转型后,才能向下转型
经验:向下转型一定要是用instanceof判断,否则可能会有类型转型异常的风险
例:
Test.java
public class Test {
public static void main(String[] args) {
//向上转型
Animal an = new Cat();
//向下转型
if(an instanceof Dog){判断引用an中存储的对象是否是Dog类
Dog dog = (Dog) an;
}else if(an instanceof Cat){//判断引用an中存储的对象是否是Cat类
Cat cat = (Cat) an;
}
}
}