简述
内部类顾名思义就是写在类内部的类,内部类最初是一种代码的隐藏机制。因为它置于类内部不仅了解外部类,并且能于之通信。普通的类一般都会被修饰为public而内部类则可以被修饰为private和default。内部类主要分为四种:成员内部类,局部内部类,静态内部类,匿名内部类。
内部类虽然是在一个类中,但是完全可以把它当成一个独立的类。这样就解决了一个类需要多继承的问题。
成员内部类和静态内部类
成员内部类就是在一个类的内部,和它的成员变量和方法是并列关系,可以理解为全局内部类。在内部类中有个很有趣的用法叫做隐式捕获,就是说在内部类中我们可以访问外部类的私有域。
静态内部类时成员内部类的一种又名嵌套类,从声明上看它只比成员内部类多了一个static。但是它和普通的成员内部类还是有些差别的:
1、嵌套类的对象和外围类的对象之间不存在联系。
2、普通的内部类中不允许存在static的数据、字段和嵌套类但是嵌套类却可以包含上述所有东西。局部内部类
内部类顾名思义就是写在类内部的类,内部类最初是一种代码的隐藏机制。因为它置于类内部不仅了解外部类,并且能于之通信。普通的类一般都会被修饰为public而内部类则可以被修饰为private和default。内部类主要分为四种:成员内部类,局部内部类,静态内部类,匿名内部类。
内部类虽然是在一个类中,但是完全可以把它当成一个独立的类。这样就解决了一个类需要多继承的问题。
内部类的分类
成员内部类和静态内部类
成员内部类就是在一个类的内部,和它的成员变量和方法是并列关系,可以理解为全局内部类。在内部类中有个很有趣的用法叫做隐式捕获,就是说在内部类中我们可以访问外部类的私有域。
静态内部类时成员内部类的一种又名嵌套类,从声明上看它只比成员内部类多了一个static。但是它和普通的成员内部类还是有些差别的:
1、嵌套类的对象和外围类的对象之间不存在联系。
2、普通的内部类中不允许存在static的数据、字段和嵌套类但是嵌套类却可以包含上述所有东西。
public class Outer {
private int param = 0;
private int getParam() {
return this.param;
}
// In inner class we can't declare a static variable unless it is a static inner class
// But we can call all members of the outer class in inner class
private class InnerClass {
private int Param = 0
private int innerClassParam = 0
public int getInnerClassParam() {
return this.innerClassParam;
}
public int getOuterClassParam() {
// If have parameter's same name between inner class with outer class, we need use outer
// class' name and '.this.' and parameter's name
return Outer.this.param;
}
}
public static void main(String[] args) {
Outer outer = new Outer();
InnerClass innerClass = outer.new InnerClass();
}
}
局部内部类
局部内部类就是写在某个作用域里的内部类,内个类只能在这个作用域中使用。通常情况下使用局部内部类有两种可能一个是使用了实现了某类型的接口,可以创建和调用其引用。第二个是需要解决某个复杂的问题,想创建一个辅助类,但又不希望是公开的。
在局部内部类中还有一种比较特殊的名为匿名内部类就是没有名字的内部类,具体请看如下代码:
public class Example {
public Contents contents() {
return new Contents() {
private int i = 11;
public int value() {
return i;
}
};
}
}
class Contents {
private int i = 11;
public int value() {
return i;
}
}
在内部类中还有一个比较重要的地方需要注意就是当内部类试图调用外部类的参数时。。查阅了很多资料都说需要将变量声明为final不然会报错。但是我在本地的环境上写代码的时候发现并没有这个问题,如下是我写的代码(PS:我使用的环境是2018年2月7日最新的jdk1.8.0_161和eclipse Oxygen版本):
public class Example {
public Destination destination(String dest) {
return new Destination() {
private String label = dest;
public String readLabel() {return label;}
};
}
public static void main(String[] args) {
Example example = new Example();
Destination destination = example.destination(1);
System.out.println(destination.readLabel());
}
}
class Destination {
private String label;
public String readLabel() {return label;}
}
这样的代码居然没有报错,感觉和很多帖子的现象是大相径庭。于是我又写了另一段代码:
public class Example {
public Destination destination(final int dest) {
return new Destination() {
private String label;
public int readLabel() {
dest += 1;
return dest;
}
};
}
public static void main(String[] args) {
Example example = new Example();
Destination destination = example.destination(1);
System.out.println(destination.readLabel());
}
}
class Destination {
private String label;
public int readLabel() {return 1;}
}
果然没有让我失望,终于报错了: The final local variable dest cannot be assigned, since it is defined in an enclosing type. 于是我找到这篇文章
内部类的Final 我猜测新版本的JDK中对内部类的引用有个改善那就是他会帮我们生成一个备份在内部类中但是当试图改变它的值时会出现错误。
为什么使用怎么使用
关于这个问题我起初也不知道该怎么回答,直到我看到了这篇文章。我觉得他解决了我的很多困惑,本着不重复造轮子的想法我就直接贴上网址了:内部类应用场景