java内部类分析
定义:将一个类定义在另一个类或者方法中,这样的类称为内部类。内部类分为四种:
- 成员内部类
- 局部内部类
- 匿名内部类
- 静态内部类
1.成员内部类
定义:类T2定义在T1内,则称T2为T1的内部类,T1为T2的外部类。
class T1{
class T2{
//..
}
}
访问原则:成员内部类可以无条件访问外部类的属性和方法,而外部类想要访问内部类属性或方法时,需要先创建一个内部类对象,然后通过内部类对象访问其属性与方法。
class T1{
private String s1 = "外部类";
public void fun1(){
System.out.println("外部类方法");
}
//外部类访问成员内部类的属性与方法
public void fun2(){
T2 t = new T2();
System.out.println(t.s2);
t.fun3();
System.out.println("外部类方法");
}
class T2{
private String s2 = "内部类";
//成员内部类访问外部类的属性与方法
public void fun3(){
System.out.println(s);
fun1();
}
}
}
注意事项:若成员内部类的属性和外部类同名,将导致外部类的属性与方法在内部类中被隐藏,但可以通过:外部类.this.属性/方法 调用。
class T1{
private String s1 = "外部类";
public void fun1(){
System.out.println("外部类方法");
}
//外部类访问成员内部类的属性与方法
public void fun2(){
T2 t = new T2();
System.out.println(t.s2);
t.fun3();
System.out.println("外部类方法");
}
class T2{
private String s1 = "内部类同名属性";
private String s2 = "内部类";
//成员内部类访问外部类的属性与方法
public void fun3(){
System.out.println(T1.this.s1);
System.out.println(s1);
fun1();
//输出 内部类同名属性,外部类,外部类方法
}
}
}
创建方式:
成员内部类寄生于外部类,因此创建在外部类外部创建内部类对象就必须先创造外部类对象。
- 外部类.内部类 内部类对象 = new 外部类().new 内部类();
- 外部类 外部类对象 = new 外部类(); 外部类.内部类 内部类对象 = 外部类对象.new 内部类();
//方式1
T1.T2 t = new T1().new T2();
//方式2
T1 t1 = new T1();
T1.T2 t2 = t1.new T2();
成员内部类的访问权限:
- private:仅外部类可以访问
- proctected:同包或继承类可以访问
- default: 同包下可访问
- public:所有类可访问
2.局部内部类
定义:类T定义在方法F内,则称T为F的局部内部类,与成员内部类的区别在于局部内部类的访问权限仅限于方法或作用域内。
class T1{
public void fun(){
class T2{
//...
}
}
}
注意事项:局部内部类就像局部变量一样,前面不能访问修饰符以及static修饰符。局部内部类如果想要使用方法形参,该形参必须使用final声明(JDK8形参变为隐式final声明)
class T1{
private int i = 1;
public void fun(){
class T2{
//...
}
}
}
public class Test2 {
public static void main(String[] args)
{
T1 t1 = new T1();
t1.fun(2);
}
}
class T1{
private int i = 1;
public void fun(final int temp){
class T2{
public void fun1(){
System.out.println(i);
System.out.println(temp);
}
}
new T2().fun1();
}
}
3.匿名内部类
定义:匿名内部类就是一个没有名字的方法内部类,因此特点和方法与局部内部类一致,除此之外,还需满足以下两点:
- 匿名内部类必须继承一个抽象类或者实现一个接口。
- 匿名内部类没有类名,因此没有构造方法。
//声明一个接口
interface i{
void fun();
}
class T1{
private int i = 1;
public void fun1(final int temp){
//匿名内部类,匿名实现了i接口
new i(){
public void fun(){
System.out.println("匿名实现MyInterface接口");
System.out.println(temp);
}
}.fun();
}
}
public class Test2{
public static void main(String[] args)
{
T1 t = new T1();
t.fun1(3);
}
}
//输出结果 匿名实现MyInterface接口 3
4.静态内部类
定义:静态内部类与成员内部类相似,不过静态内部类使用static关键字进行修饰,而两者区别在于:非静态内部类在编译完成后会保存着引用,该引用指向创建它的外部类,而静态内部类没有,因此,静态内部类可以实现:
- 静态内部类的创建不需要依赖外部类就可以直接创建。
- 静态内部类不可以使用任何外部类的非static类(包括属性和方法),但可以存在自己的成员变量。
class T1{
private String s1 = "外部类";
private static int i = 1;
public void fun1(){
System.out.println("外部类方法");
}
//声明静态内部类
static class T2{
private String s2 = "静态内部类";
//成员内部类访问外部类的属性与方法
public void fun2(){
System.out.println(s1);
System.out.println(i);
fun1();
}
}
}
创建方式:
成员内部类寄生于外部类,但由于静态内部类的创建不需要依赖外部类就可以直接创建,所以可以使用下列方式创建。
外部类.内部类 内部类对象 = new 外部类.内部类();
//不需要创建外部类就
T1.T2 t = new T1.T2();
//注意与非静态内部类的创建方式区别
//第一个new为创建外部类对象后通过外部类对象再new 内部类()完成创建。
T1.T2 t = new T1().new T2();