一、成员内部类
public class OutClass {
private int age = 1;
private static int staticAge = 2;
private static void test(){
System.out.println("静态的test");
}
class Inner{
public void show(){
System.out.println(age); //1
}
}
static class staticInner{
public void show(){
System.out.println(age); //报错
System.out.println(staticAge); //2
test();
}
}
public static void main(String[] args) {
OutClass.Inner oi = new OutClass().new Inner();
oi.show();
OutClass.staticInner os = new OutClass.staticInner();
os.show();
}
}
成员内部类就是跟成员变量在同一位置的类
可以调用外部类所有的成员变量和成员方法,包括private修饰的
创建对象的时候,分成员内部类是否是静态的,根据上图代码可以看出区别,被静态修饰后,只能调用外部类的静态成员变量和静态成员方法
如果使用private修饰内部类,那么就无法使用其他类创建对象的方式来访问内部类(上图代码中是在本类中的main方法,这块说的是其他类)
应用场景:可以给内部类添加一个public的get方法,比如说参数可以是用户的角色,如果是普通用户就返回null,如果是管理员账户就返回内部类对象
class Outer {
public int age = 18;
class Inner {
public int age = 20;
public viod showAge() {
int age = 25;
System.out.println(age);//25
System.out.println(this.age);//20
System.out.println(Outer.this.age);//18
}
}
}
//来源 : https://www.zhihu.com/question/26954130
二、静态内部类
public class TestStatic {
private String str = "不是静态的";
private static String str2 = "静态的";
static class testStaticClass{
private void show(){
System.out.println("静态内部类的方法输出");
System.out.println(str); //报错,编译不通过
System.out.println(str2);//正常输出
}
}
public static void main(String[] args) {
TestStatic.testStaticClass tts = new TestStatic.testStaticClass();
tts.show();
}
}
static是不能修饰类的,但是成员内部类相当于是一个成员,所以可以使用static进行修饰,被static修饰的成员内部类被称为静态内部类
不能使用外部类的非静态的成员变量和成员方法
非静态的内部类编译后会默认保存一个指向外部类的引用,而静态类没有
即使没有外部类对象,也可以创建静态内部类对象,而外部类的非static成员必须依赖于对象的调用,静态成员则可以直接使用类调用,不必依赖于外部类的对象,所以静态内部类只能访问静态的外部属性和方法。其实还是static的本身原因,static为类变量,类方法,而非static的是对象的变量和对象的方法,类的内容在类初始化的时候就已经加载了,所以调用外部非static的时候会报错
三、局部内部类
public class TestJuBu {
private String str = "成员变量";
public void test(){
String str2 = "局部变量";
class InnerClass{
public void show(){
System.out.println("局部的show");
System.out.println(str);
System.out.println(str2);
}
}
InnerClass in = new InnerClass();
in.show();
}
public static void main(String[] args) {
TestJuBu t = new TestJuBu();
t.test();
}
}
定义在成员方法内部,跟局部变量同级的类就是局部内部类,在方法内部进行调用
为什么局部内部类访问局部变量必须加final修饰呢? ---> 用final修饰实际上就是为了保护数据的一致性。
这块的局部变量并没有使用final修饰,这是jdk1.8之后的语法糖,使用反编译软件查看后,还是有final修饰符
jdk1.8之前,局部内部类使用的局部变量如果没有加final,是无法编译通过的,主要是为了数据的一致性。通过反编译软件可以看到,局部内部类中的局部变量实际上是通过构造方法传入的,如果不用final进行修饰,那么这个变量的引用是可以改变的,局部内部类引入的时候,只是引入了地址或者值赋值给了新的变量,外面的引用变化之后,内部类并不知道这个值发生了变化,就会出现问题。
四、匿名内部类
一个没有名字的类,是内部类的简化写法
本质:其实是继承该类或者实现接口的子类匿名对象
public class TestNiMing {
private void test(){
new Outer(){
public void show(){
System.out.println("匿名内部类输出");
}
}.show();
}
public static void main(String[] args) {
TestNiMing t = new TestNiMing();
t.test();
}
}
interface Outer{
public abstract void show();
}
如果有多个方法:
public class TestNiMing2 {
private void test(){
Outer2 o = new Outer2(){
public void show(){
System.out.println("匿名内部类输出");
}
public void show2(){
System.out.println("第二个输出");
}
};
o.show();
o.show2();
}
public static void main(String[] args) {
TestNiMing2 t = new TestNiMing2();
t.test();
}
}
interface Outer2{
public abstract void show();
public abstract void show2();
}
参考链接中,对匿名内部类的举例代码有问题,作者的意思应该如下
public class MyDemo{
public void test(Demo demo){
demo.demoMethod();
System.out.println("test method");
}
public static void main(String[] args) {
MyDemo md = new MyDemo();
//这里我们使用匿名内部类的方式将接口对象作为参数传递到test方法中去了
md.test(new Demo(){
public void demoMethod(){
System.out.println("具体实现接口");
}
});
}
}
interface Demo {
void demoMethod();
}
输出为:
具体实现接口
test method
参考链接: