1.成员内部类
1.样例
class OutClass {
class InnerClass {
public String SayHi() {
return "你好";
}
}
}
2.特点
- 内部类能够无条件的访问外部类的成员变量,外部类要访问内部类成员变量需要使用new。
- 内部类和外部类有相同名称的变量或者是方法,访问外部类方式为:外部类.this.方法。
- 内部类是依赖外部类的,只有先有外部类才能有内部类。调用内部类方法为:
OutClass out = new OutClass();
OutClass.InnerClass inner = out.new InnerClass();
- 内部类的权限可以public,protected,保护类型和private。而外部类只能是public和保护类型。
- 成员内部类不能存在static关键字,非静态内部类也可以定义静态成员但需要同时有final关键词修饰。
2.局部内部类
public class Outer {
private int s = 100;
private int out_i = 1;
public void f(final int k) {
final int s = 200;
int i = 1;
final int j = 10;
// 定义在方法内部
class Inner {
int s = 300;// 可以定义与外部类同名的变量
// static int m = 20;//不可以定义静态变量
Inner(int k) {
inner_f(k);
}
int inner_i = 100;
void inner_f(int k) {
// 如果内部类没有与外部类同名的变量,在内部类中可以直接访问外部类的实例变量
System.out.println(out_i);
// 可以访问外部类的局部变量(即方法内的变量),但是变量必须是final的
System.out.println(j);
// System.out.println(i);
// 如果内部类中有与外部类同名的变量,直接用变量名访问的是内部类的变量
System.out.println(s);
// 用this.变量名访问的也是内部类变量
System.out.println(this.s);
// 用外部类名.this.内部类变量名访问的是外部类变量
System.out.println(Outer.this.s);
}
}
new Inner(k);
}
public static void main(String[] args) {
// 访问局部内部类必须先有外部类对象
Outer out = new Outer();
out.f(3);
}
}
是指内部类定义在一个类的方法,代码块中。
- 局部内部类只能在代码代码块、方法体内和作用域中使用(如创建对象和使用类对象等)
- 局部内部类访问作用域内的局部变量,该局部变量需要使用final修饰。
- 可以使用abstract修饰,声明为抽象类。
- 只能在定义该类的方法中实例化。
3.静态内部类
public class Outer {
private static int i = 1;
private int j = 10;
public static void outer_f1() {}
public void outer_f2() {}
// 静态内部类可以用public,protected,private修饰
// 静态内部类中可以定义静态或者非静态的成员
private static class Inner {
static int inner_i = 100;
int inner_j = 200;
static void inner_f1() {
// 静态内部类只能访问外部类的静态成员(包括静态变量和静态方法)
System.out.println("Outer.i" + i);
outer_f1();
}
void inner_f2() {
// 静态内部类不能访问外部类的非静态成员(包括非静态变量和非静态方法)
// System.out.println("Outer.i"+j);
// outer_f2();
}
}
public void outer_f3() {
// 外部类访问内部类的静态成员:内部类.静态成员
System.out.println(Inner.inner_i);
Inner.inner_f1();
// 外部类访问内部类的非静态成员:实例化内部类即可
Inner inner = new Inner();
inner.inner_f2();
}
public static void main(String[] args) {
new Outer().outer_f3();
}
}
使用static修饰的内部类。
- 不依赖外部类,不能使用外部类非静态的变量和方法。
- 不需要如成员内部类一样,生成外部类对象来生成内部类。
- 静态内部类中可以定义静态或者非静态的成员。
- 外部类访问内部类的静态成员:内部类.静态成员。
- 外部类访问内部类的非静态成员:实例化内部类即可。
- 可以有非静态的方法或者变量。
3.使用场景
- 当外部需要使用内部类而内部类不依赖与外部类的资源。
- 能够单独生成对象。
- 节省资源。
4.匿名内部类
就是没有名字的内部类。匿名内部类的格式:
new 接口或父类(){
重写抽象方法
};
2.应用场景
个人理解就是没有实现一个接口,但是想重写接口中的方法并且调用并返回。
目的:
- 可以使命名变得简洁。
- 使代码更加紧凑,简洁,封装性比内部类更优。
- 一个类用于继承其他类或是实现接口,无需增加其他的方法,只是对继承方法实现 覆盖。
public class OuterClass {
public InnerClass getInnerClass(final int num,String str2){
return new InnerClass(){
int number = num + 3;
public int getNumber(){
return number;
}
}; /* 分号不能省 */
}
public static void main(String[] args) {
OuterClass out = new OuterClass();
InnerClass inner = out.getInnerClass(2, "chenssy");
System.out.println(inner.getNumber());
}
}
interface InnerClass {
int getNumber();
}
----------------
Output:
5
如果不适用匿名内部类
interface InnerClass {
int getNumber(int a);
}
class InnerClassImpl{
int getNumber(int a){
system.out.print(a);}
}
InnerClass InnerClass = new InnerClassImpl();
使用匿名内部类之后
InnerClass InnerClass = new InnerClass (){
public int getNumber(int a){
return a;
}
}
特点:
- 匿名内部类是没有访问修饰符的。
- new 匿名内部类,这个类首先是要存在的。如果我们将那个InnerClass接口注释掉,就会出现编译出错。
- 注意getInnerClass()方法的形参,第一个形参是用final修饰的,而第二个却没有。同时我们也发现第二个形参在匿名内部类中没有使用过,所以当所在方法的形参需要被匿名内部类使用,那么这个形参就必须为final。
- 匿名内部类是唯一一种没有构造方法的类。
- 匿名内部类不能定义任何静态成员、方法和类。
5.使用内部类的原因:
- 可以实现多重继承。(不同的内部类可以继承不同的类)。
- 内部类可以更好的隐藏。
- 当我们不想写接口的实现或只是用一次对象时可以使用匿名内部类。
- 每个内部类都是一个单独的个体。