内部类
内部类的精华: 匿名内部类, 而匿名内部类的作用恰恰就是简化了代码, 让我们可以少些一个类(实现类)
内部类说白了, 就是类中嵌套定义一个类.虽然方法与方法之间不能嵌套定义, 但是类却能够嵌套, 类似于
1 2 3 4 5 6
| public class Car{ public class Engine{ } }
|
成员内部类
就是在类中成员变量/成员方法的位置, 定义了一个内部类, 类似于成员变量、成员方法。
代码举例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| public class Outer { private int age = 99; public static String a="小王";
public class Inner{ private String name; private int age = 88;
public void test(){ System.out.println(age); System.out.println(a);
int age = 77; System.out.println(age); System.out.println(this.age); System.out.println(Outer.this.age); }
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; } } }
|
注意事项:
1 2 3 4
| Outer.Inner in = new Outer().new Inner();
in.test();
|
内部类访问成员的特点
- 既可以访问内部类成员、也可以访问外部类成员
- 如果内部类成员和外部类成员同名,可以使用**
外部类名.this.成员**区分
静态内部类
静态内部类,其实就是在成员内部类的前面加了一个static关键字。静态内部类属于外部类自己持有。
代码举例
1 2 3 4 5 6 7 8 9 10 11 12 13
| public class Outer { private int age = 99; public static String name = "小威";
public static class Inner{ public void test(){ System.out.println(name); } } }
|
注意事项
- 定义静态内部类,就是在定义成员内部类的位置定义,顺便多了一个Static修饰符。
- 定义静态内部类,内部类只能访问外部类的静态变量,但是不能访问外部类的实例变量。
创建内部类的对象的格式为:
1 2 3
| Outer.Inner in = new Outer.Inner(); in.test();
|
局部内部类
局部内部类是定义在方法中的类,和局部变量一样,只能在方法中有效。所以局部内部类的局限性很强,一般在开发中是不会使用的。
代码举例
1 2 3 4 5 6 7 8 9 10 11 12 13
| public class OuterPartInner { public void test(){ class Inner{ public void show(){ System.out.println("Inner....show"); } }
Inner in = new Inner(); in.show(); } }
|
注意事项
- 局部内部类(是在类中方法的局部变量位置定义的类)在外部创建不了对象
匿名内部类
精华:匿名内部类是1个继承了该类, 或者实现了该接口的匿名的子类对象.
代码举例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| public abstract class Animal{ public abstract void cry(); }
public class Test { public static void main(String[] args) { Animal a = new Animal() { @Override public void cry() { System.out.println("喵喵喵?-猫"); } }; a.cry(); } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| public class A implements Swimming{ @Override public void swim() { System.out.println("A游泳....."); } }
public class Test { public static void main(String[] args) { A a = new A(); go(a);
go(new Swimming() { @Override public void swim() { System.out.println("匿名内部类...游泳...."); } }); }
public static void go(Swimming s){ s.swim(); } }
|
注意事项
匿名内部类其实有隐含的多态的特性,Animal a = Animal子类对象
- 匿名内部类在编写代码时没有名字,编译后系统会为自动为匿名内部类生产字节码,字节码的名称会以
外部类$1.class的方法命名

枚举
总结:枚举是一种特殊的类,它的格式是:
1 2 3
| public enum 枚举类名{ 枚举项1,枚举项2,枚举项3; }
|
同时,可以在枚举类中写构造方法(空参,全参),成员方法,成员变量。
枚举的应用示例
总结一下枚举的应用场景:枚举一般表示几个固定的值,然后作为参数进行传输。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| public enum Sex { Man, Women; }
public class MySystem { public void recommend(Sex sex){ switch (sex){ case Man: System.out.println("都市修仙"); break; case Women: System.out.println("宫斗"); break; } } }
public class Test { public static void main(String[] args) { MySystem s = new MySystem(); s.recommend(Sex.Man); s.recommend(Sex.Women); } }
|
注意事项
- 枚举中的前几个枚举都是对象,可以调用枚举类中的成员方法,成员变量。例如
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| public enum A { X,Y,Z; public void show(){ System.out.println("A...show..."); } }
public class TestA { public static void main(String[] args) { A.X.show(); A.Y.show(); A.Z.show();
System.out.println(A.X); System.out.println(A.Y); System.out.println(A.Z); System.out.println(A.X.compareTo(A.Z));
A y = Enum.valueOf(A.class, "Y"); y.show(); } }
|
泛型
泛型概述
所谓泛型指的是,在定义类、接口、方法时,同时声明了一个或者多个类型变量(如:<E>),称为泛型类、泛型接口、泛型方法、它们统称为泛型。
Tips:
- 注意泛型的<>里面可以写<E, K, T, V>等表示泛型的字母(Element, Key, Value, Type)
- 泛型可以修饰类, 接口 和 方法(一般是在类名, 接口名的后面加上<E,K,T,V>, 但是
泛型方法是在返回值类型前面写的)
- 比如ArrayList类就是一个泛型类
确定泛型值的时机(※)
泛型类
- 1: 在
设计实现类的时候,直接写死;
- 2: 设计实现类的时候也带泛型,将来
创建实现类对象的时候,确定泛型的值;
泛型接口
泛型方法及泛型通配符
泛型类
就是在类名的后面加上<E,K,T,V>这种,像ArrayList <E>这样的,但是自己定义泛型类是非常少的。
自定义泛型类的格式如下
1 2 3 4
| public class 类名<T,W>{ }
|
代码示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| public class Box<MoMo> { private MoMo element; public MoMo getElement() { return element; }
public void setElement(MoMo element) { this.element = element; }
public Box() { }
public Box(MoMo element) { this.element = element; } }
public class Test { public static void main(String[] args) { Box<String> box = new Box<>("abc");
String element = box.getElement(); System.out.println(element); } }
|
注意事项
- 泛型类的类型确定可以在实例化对象的时候确定,也可以在设计泛型类的时候直接填写
泛型接口
泛型接口其实指的是在接口中把不确定的数据类型用<类型变量>表示。定义格式如下:
1 2 3 4
| public interface 接口名<类型变量>{ }
|
比如,我们现在要做一个系统要处理学生和老师的数据,需要提供2个功能,保存对象数据、根据名称查询数据,要求:这两个功能处理的数据既能是老师对象,也能是学生对象。
首先我们得有一个学生类和老师类
1 2 3
| public class Teacher{
}
|
1 2 3
| public class Student{ }
|
我们定义一个Data<T>泛型接口,T表示接口中要处理数据的类型。
1 2 3 4 5
| public interface Data<T>{ public void add(T t); public ArrayList<T> getByName(String name); }
|
接下来,我们写一个处理Teacher对象的接口实现类
1 2 3 4 5 6 7 8 9 10 11
|
public class TeacherData implements Data<Teacher>{ public void add(Teacher t){ } public ArrayList<Teacher> getByName(String name){ } }
|
接下来,我们写一个处理Student对象的接口实现类
1 2 3 4 5 6 7 8 9 10 11
|
public class StudentData implements Data<Student>{ public void add(Student t){ } public ArrayList<Student> getByName(String name){ } }
|
再啰嗦几句,在实际工作中,一般也都是框架底层源代码把泛型接口写好,我们实现泛型接口就可以了。
泛型接口的类型传递顺序

泛型方法
泛型方法的定义相对于泛型类和泛型接口有些特殊,泛型方法是在方法返回值前面定义的。
代码示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| public static <T> void test(T t){ return t; }
public class Test{ public static void main(String[] args){ String rs = test("test"); Dog d = test(new Dog()); } public static <T> test(T t){ return t; } }
|
注意事项
泛型通配符
- > 表示任意类型
- extends 数据类型> 表示是否继承自后面的类
- super 数据类型> 表示是否是后面类的爹
代码示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| public class Test { public static void main(String[] args) { ArrayList<Object> list = new ArrayList<>(); ArrayList<Integer> integer = new ArrayList<>(); ArrayList<Number> number = new ArrayList<>(); ArrayList<Object> object = new ArrayList<>();
m1(integer); m1(number);
m2(number); m2(object); } public static void m1(ArrayList<? extends Number> list){
}
public static void m2(ArrayList<? super Number> list){
} }
|
注意事项
泛型通配符的取值范围通常是闭区间,就是能够取到后面的数据类型
泛型擦除
也就是说泛型只能编译阶段有效,一旦编译成字节码,字节码中是不包含泛型的。而且泛型只支持引用数据类型,不支持基本数据类型。

反编译后
