一、内部类
内部类是类中的五大成分之一(成员变量、方法、构造器、内部类、代码块),如果一个类定义在另一个类的内部,这个类就是内部类。
当一个类的内部,包含一个完整的事物,且这个事物没有必要单独设计时,就可以把这个事物设计成内部类。
比如:汽车、的内部有发动机,发动机是包含在汽车内部的一个完整事物,可以把发动机设计成内部类。
内部类有四种形式,分别是成员内部类、静态内部类、局部内部类、匿名内部类。
public class Demo01 {
public static void main(String[] args) {
Outer o = new Outer();
o.method();
//内部类对象必须通过外部类才能访问,所以要先创建外部类对象
//总结一下内部类访问成员的特点
//- 既可以访问内部类成员、也可以访问外部类成员
//- 如果内部类成员和外部类成员同名,可以使用类名.this.成员区分
Outer.Inner oi = new Outer().new Inner();
oi.show();
System.out.println("--------------------");
//静态内部类,优先于外部类对象存在
//静态内部类创建对象时,需要使用外部类的类名调用。
Outer.Inner1 oi1 = new Outer.Inner1();
oi1.show();
//匿名内部类(建议只使用一次的情况下使用,某个方法使用抽象类或接口作为参数时用,如果要重写的方法超过2个就不建议使用匿名内部类的方式)
//匿名内部类写外面的话可以使用多态的方式接受:父类引用指向子类对象
//需要注意的是,匿名内部类在编写代码时没有名字,编译后系统会为自动为匿名内部类生产字节码,字节码的名称会以外部类$1.class的方法命名
go(new Swim() {
@Override
public void swimming() {
System.out.println("游泳");
}
});
public static void go(Swim s){
System.out.println("开始=======");
s.swimming();
}
}
class Outer {
public void method() {
System.out.println(a);
}
private int a = 10;
static int b = 20;
//outer的成员,同成员方法一样
class Inner {//成员内部类
int a = 100;
public void show() {
int a = 1000;
System.out.println(a);
System.out.println(this.a);
System.out.println(Outer.this.a);
}
}
//静态内部类,其实就是在成员内部类的前面加了一个static关键字。
//静态内部类属于外部类自己持有。
static class Inner1 {
int a = 100;
public void show() {
int a = 1000;
System.out.println(a);
System.out.println(this.a);
//静态不能调非静态
//创建对象
Outer o = new Outer();
System.out.println(o.a);
System.out.println(b);//静态直接用
}
}
}
interface Swim{
void swimming();
}
//局部内部类是定义在方法中的类,和局部变量一样,只能在方法中有效。
//所以局部内部类的局限性很强,一般在开发中是不会使用的。
//局部内部类只能在方法中创建对象,并使用
二、枚举
枚举是一种特殊的类,它的格式是:
public enum 枚举类名{
枚举项1,枚举项2,枚举项3;
}
作为参数,用于限制调用者传参,只能从我的枚举项中选择
注意事项:
1. 枚举项必须在类中的第一行
2. 每一个枚举项,都是一个该枚举类的一个对象
3. 枚举类不能创建对象,因为私有构造方法
4. 枚举类不能被继承,被final修饰
5. 枚举类提供了一个方法供我们使用,values():获取装有所有枚举项的一个数组
三、泛型
所谓泛型指的是,在定义类、接口、方法时,同时声明了一个或者多个类型变量(如:<\E>),称为泛型类、泛型接口、泛型方法、它们统称为泛型。
编写者:就是一种未知的数据类型。
使用者:创建对象时,调用方法时,实现接口时指定具体的数据类型。
泛型类:
class MyClass<E>{}
创建对象时
泛型方法:
public <T> void show(T t){}
调用方法时
泛型接口:
interface Inter<T> {}
实现接口时
通配符:
?:不限制类型
? extends E: 只能传E或者E的子类
? super E: 只能传E或者E的父类
泛型擦除。什么意思呢?
也就是说泛型只能编译阶段有效,一旦编译成字节码,字节码中是不包含泛型的。
而且泛型只支持引用数据类型,不支持基本数据类型。
总结一下泛型的作用、本质:
- 泛型的好处:在编译阶段可以避免出现一些非法的数据。
- 泛型的本质:把具体的数据类型传递给类型变量。