成员内部类、方法内部类、静态内部类、匿名内部类
一、成员内部类
成员内部类定义在外部类的成员位置上(如成员变量和成员方法);编译之后会生成两个class文件;成员内部类可以访问外部类的静态和非静态的方法和成员变量;创建内部类对象必须使用外部类对象,而不能直接new一个内部类对象,先创建外部类对象,Outer outer = new Outer();再创建内部类对象Outer.Inner inner = outer.new Inner();外部类不可直接访问内部类成员变量。
总结成员内部类的注意事项:
1、成员内部类不允许存在任何static变量或者方法;
2、成员内部类是依附性的,只有创建了外部类才能创建内部类。
package exam;
class Outer
{
private int id = 1314190510;
private String username = "xiaoqiang";
class Iner
{
static int m = 0;
public void test()
{
System.out.println(username+"的编号为:"+id);
}
}
}
public class ByteDance
{
public static void main(String[] args)
{
Outer.Iner pint = new Outer().new Iner();
pint.test();
}
}
由于以上代码在成员内部类定义了一个静态属性,因此运行程序会报错
Exception in thread "main" java.lang.Error: Unresolved compilation problem:
The field m cannot be declared static in a non-static inner type, unless initialized with a constant expression
at exam.Outer$Iner.<init>(ByteDance.java:9)
at exam.ByteDance.main(ByteDance.java:24)
二、方法内部类
方法内部类顾名思义就是定义在方法里的类;不能使用任何的访问修饰符;在方法中定义的内部类只能访问方法中final类型的局部变量,因为用final定义的局部变量相当于是一个常量,它的生命周期超出方法运行的生命周期。
总结方法内部类的注意事项:
1、方法内部类不允许使用访问权限修饰符(public、private、protected)均不允许。
2、方法内部类对外部完全隐藏,除了创建这个类的方法可以访问它以外,其他地方均不能访问 (换句话说其他方法或者类都不知道有这个类的存在)方法内部类对外部完全隐藏,出了创建这个类的方法可以访问它,其他地方均不能访问。
3、方法内部类如果想要使用方法形参,该形参必须使用final声明。
package exam;
class Outer
{
public int id = 1314190510; ///使用外部类参数的修饰权限定义是没有要求的
public String username = "xiaoqiang";
public void test(int id)
{
int test = 000;方法内部类参数
class Iner 不能使用权限修饰符
{
public void print()
{
System.out.println(id);使用外部类的参数需要是final类型的
}
}
new Iner().print();
}
}
public class ByteDance
{
public static void main(String[] args)
{
Outer out = new Outer();
out.test(12);
}
}
上述代码主要验证第三条结论,为什么方法的形参没有定义为final也仍然能够运行成功呢?这是因为JDK8默认的形参类型为final类型,此时将方法形参修改为任何一种修饰符进行修饰,运行程序,此时抛出异常:
Exception in thread "main" java.lang.Error: Unresolved compilation problem:
Illegal modifier for parameter id; only final is permitted
at exam.Outer.test(ByteDance.java:7)
at exam.ByteDance.main(ByteDance.java:30)
三、匿名内部类
所谓的匿名内部类是一个没有显式名字的内部类,它隐式的继承了一个类或者实现了一个接口;return new A(){///内部类体};在匿名内部类结束时,需要加分号标识;匿名内部类访问的外部类成员变量或者成员方法必须用static修饰。
总结匿名内部类的注意事项:
1、匿名内部类必须继承一个抽象类或者实现一个接口
2、.匿名内部类没有类名,因此没有构造方法
3、在匿名内部类结束时,需要加分号标识
4、匿名内部类访问的外部类成员变量或者成员方法必须用static修饰。
package exam;
abstract class myclass
{
public void test()
{
}
}
class Outer
{
int m = 0;
public void print()
{
new myclass() ///继承一个抽象类,重写抽象类中的方法
{
public void test()
{
System.out.print("我是匿名内部类!"+m);
}
}.test();
}
}
public class ByteDance
{
public static void main(String[] args)
{
Outer out = new Outer();
out.print();
}
}
四、静态内部类
定义在成员位置上,并且用static修饰的内部类。静态内部类如果要访问外部的成员变量或者成员方法,那么必须是静态的;在静态类内部可以声明static成员,但是在非静态内部类中不可声明静态成员。
总结静态内部类的注意事项:
1、.静态内部类的创建不需要依赖外部类可以直接创建。
2、静态内部类不可以使用任何外部类的非static类(包括属性和方法),但可以存在自己的成员变量。
package exam;
class Outer
{
private int id = 123;
static class Iner
{
private String name = "xiaoming";
public void print()
{
System.out.print(name);
}
}
}
public class ByteDance
{
public static void main(String[] args)
{
Outer.Iner in = new Outer.Iner();
in.print();
}
}