我发现最近真是越来越没有东西写了。。。不可能天天学习新知识啊,最近在复习阶段了,复习的东西大多数是博客里写过的/(ㄒoㄒ)/
复习Java基础的时候认真看了一下Java的内部类,这东西之前了解过,但是没有写过代码实验一下,今天就来手写代码夯实夯实基础。也懒得写那么多文字了,博客精简一点剩下时间用来复习。
Java中的内部类分为:
+ 普通内部类:也叫成员内部类
+ 局部内部类
+ 静态内部类
+ 匿名内部类
普通内部类
普通内部类就是直接写在宿主类中的(我这篇文章中称为宿主类,和外部类区分开),并且不带static,如下:
public class TestInnerClass {
private String outerName = "outer";
//普通内部类
public class InnerClass1{
// 普通内部类可以访问宿主类的一切属性
public String name = outerName+": "+"InnerClass1";
}
@Test
public void testNormal(){
// 创建一个普通内部类对象
InnerClass1 innerClass1 = new InnerClass1();
// 宿主类可以访问其属性
System.out.println(innerClass1.name);
}
}
为什么普通内部类可以带public
这种访问修饰符呢?外部类可以创建一个它的实例对象吗?
验证如下:
public class TestInnerClass2 {
@Test
public void test(){
// 首先创建一个宿主类的对象
TestInnerClass t = new TestInnerClass();
// 通过宿主类的对象new出一个内部类的对象
TestInnerClass.InnerClass1 innerClass1 = t.new InnerClass1();
// 可以获取内部类public的属性
System.out.println(innerClass1.name);
}
}
普通内部类是依存于宿主类的实例对象存在的,通过宿主类的实例对象才能new出一个内部类的实例,不得不说,这个语法还蛮少见的。
当然,如果普通内部类声明为private的,外部类就不可以访问了。
局部内部类
局部内部类是宿主类的一个方法中的,比较特殊:
public class TestInnerClass3 {
@Test
public void test(){
String methodName = "test";
// 局部内部类,生效范围为方法内部作用域
class InnerClass3{
// 可以获取方法中声明的局部变量
public String className = methodName+": InnerClass3";
}
// 在方法中可以使用
InnerClass3 innerClass3 = new InnerClass3();
System.out.println(innerClass3.className);
}
}
但是局部内部类有一个特点是不能加上访问权限限定符,例如public、private:
public class TestInnerClass3 {
@Test
public void test(){
String methodName = "test";
// 报错!!!
public class InnerClass3{
public String className = methodName+": InnerClass3";
}
InnerClass3 innerClass3 = new InnerClass3();
System.out.println(innerClass3.className);
}
}
但是可以加上abstract、final这样的修饰符。
静态内部类
静态内部类和普通的类最为相似,唯一的区别可以看作就是要通过一个类来获取。这种内部类平时也是用的比较多的,所以这里也不特别说明。
public class TestInnerClass4 {
private static String className = "TestInnerClass4";
public static class InnerClass4{
// 只能获取宿主类的静态字段
private String name = className+": InnerClass4";
}
}
匿名内部类
匿名内部类平时也用的特别多,常见的例子就是new一个Thread:
public class TestInnerClass5 {
public static void main(String[] args) {
new Thread(){
@Override
public void run() {
System.out.println("线程启动");
}
}.start();
}
}
这里实际上是创建了一个Thread的子类,并重写了run方法。
会不会生成单独的class文件
经过测试,所有内部类都会产生单独的class文件,并且命名是:
- 普通内部类和静态内部类都是:
(宿主类名)$(内部类名)
- 局部内部类是:
(宿主类名)$(编号)(内部类名)
- 匿名内部类是:
(宿主类名)$(编号)
普通内部类能访问宿主类实例字段的原理
- 编译器自动为内部类添加一个成员变量,该成员变量的类型和外部类的类型相同,这个成员变量就是指向外部类对象引用。
- 编译器自动为内部类的构造方法添加一个参数,参数的类型是外部类的类型,在构造方法内部使用这个参数为1中添加的成员变量赋值。
- 在调用内部类的构造函数初始化内部类对象时,会默认传入外部类的引用。
原创文章,作者:彭晨涛,如若转载,请注明出处:https://www.codetool.top/article/java%e4%b8%ad%e7%9a%84%e5%9b%9b%e7%a7%8d%e5%86%85%e9%83%a8%e7%b1%bb/