内部类
在一个类的内部又定义了一个类,里面的这个类就是内部类。
成员内部类
成员内部类是最普通的内部类,它的定义为位于另一个类的内部。
成员内部类可以参照成员属性、成员方法来理解,把内部类看做是外部类的一个成员,内部类可以拥有private访问权限、protected访问权限、public访问权限及包访问权限。
内部类访问外部类 成员内部类可以无条件访问外部类的所有成员属性和方法(包括private成员和静态方法)。
但是要注意,当内部类与外部类的方法名相同时,在内部类会默认使用内部类的成员方法,要想使用外部类的方法,需要 ‘外部类.this.成员变量’ 访问。class OutsideClass{ private int a = 1; static int b=2; private void meth1(){ System.out.println("外部类方法"); } public void meth2(){ System.out.println("同名方法_外部类"); } class InnerClass{ public void callOutside(){ System.out.println(a);//调用外部类private属性 System.out.println(b);//调用外部类静态属性 meth1();//调用外部类方法 meth2();//输出“同名方法_内部类”,内部类方法与外部类方法同名,所以会默认调用本类(内部类)的方法。 OutsideClass.this.meth2();//输出“同名方法_外部类”。 } public void meth2(){ System.out.println("同名方法_内部类"); } } }
外部类访问成员内部类 需要先创建内部类对象,再通过这个对象来访问。
在方法中创建内部类对象:成员内部类是依附于外部类存在的,所以要创建内部类对象,必须存在一个外部类对象,可以这样创建:
class Test{
public static void main(String[] args){
//第一种创建
OutsideClass outter=new OutsideClass();
OutsideClass.InnerClass inner1= outter.new InnerClass();
//第二种创建
OutsideClass.InnerClass inner2=new OutsideClass().new InnerClass();
}
}
局部内部类
局部内部类是定义在一个方法或者一个作用域里面的类,它和成员内部类的区别在于局部内部类的访问仅限于方法内或者该作用域内。
局部内部类可以参照普通方法中的局部变量来理解,把局部内部类看做是方法里面的一个局部变量,不能有public、protected、private以及static修饰符的。
局部内部类要想访问 该内部类所在方法的局部变量 ,这个局部变量必须加final修饰符,(1.8以后不用加,但会默认的自动加上。)
局部内部类可以访问外部类的所有成员属性、方法。
class Test{ public static void main(String[] args){ } public void meth3(){ int a = 1; final int b = 2; class LocalInner { public void meth4{ System.out.println(a);//在这调用过 方法中的局部变量后,该变量自动转换为 final修饰的常量 //a = 10; // X 这句代码会出错,因为在内部类中调用过 a 所以a为final修饰的常量,常量不能再修改。 System.out.println(b); meth3(); //调用外部类的方法 注意 调用该方法会使程序陷入死循环 } } //a = 10; // X 这句代码也会出错,因为在内部类中调用过 a 所以a为final修饰的常量,常量不能再修改。 LocalInner loca1=new LocalInner(); loca1.meth4(); // 调用局部内部类方法 } }
匿名内部类 ———— 最常用 可和局部内部类相似
本质上是一个继承了类或者实现了接口的子类匿名对象,————相当于先创建了一个类,然后再通过这个类创建了一个对象(可以参考下面的例子)
可以写成成员变量的形式,也可以写在方法中
访问外部类成员属性与方法,与局部内部类一样,参照局部内部类即可。
匿名内部类没有构造器,它没有名字,所以不能在其他地方使用
public class AnonymousInnerClass {
//匿名内部类写成成员变量的形式,实现了Animal接口
Animal animal=new Animal() {
@Override
public void eat() {
// TODO 自动生成的方法存根
}
};
int a =5;
public static void main(String[] args) {
Cat cat1=new Cat();
Animal cat2=new Cat();
//写到方法中,创建了一个匿名内部类,然后改内部类创建了一个对象,可以通过该对象名直接访问匿名内部类中的成员变量及方法
Animal animal=new Animal() {
@Override
public void eat() {
// TODO 自动生成的方法存根
System.out.println("匿名内部类吃");
}
};
animal.eat();
int a =10;
//创建了一个匿名内部类的匿名对象,可以直接通过 +.成员属性方法 来访问匿名内部类成员属性方法
new Animal() {
int a =20;
@Override
public void eat() {
// TODO 自动生成的方法存根
int a=30;
System.out.println("匿名内部类 猫吃");
System.out.println(this.a);
}
}.eat(); //通过 +.成员属性方法 来访问匿名内部类成员属性方法
}
}
interface Animal{
void eat();
}
class Cat implements Animal{
public void eat() {
System.out.println("猫吃");
}
}
静态内部类 ———— 不常用
静态内部类相当于是内部类加上static修饰,它不需要依赖于外部类,与类的静态属性相似
静态内部类相当于另外的一个类,创建静态内部类对象时,不需要创建内部类对象,可以直接创建静态内部类对象。”外部类.静态内部类 对象名=new 外部类.静态内部类构造器;” 或者 先把外部类导包
静态内部类不可以使用外部类的非静态属性和非静态方法。(这个可以通过类加载的顺序来理解)
public class StaticClass { public static void main(String[] args) { OutsideClass_Static.InnerClasss_Static innerClasss_Static = new OutsideClass_Static.InnerClasss_Static(); innerClasss_Static.meth(); } } class OutsideClass_Static{ static int a=1; int b = 2; static void meth_Static() { System.out.println("外部类静态方法"); } void meth_NoStatic() { System.out.println("外部类非静态方法"); } static class InnerClasss_Static{ public void meth() { System.out.println(a);//可以调用 System.out.println(b);//会出现编译错误,不能调用外部类非静态成员属性 meth_Static();//可以调用 meth_NoStatic();//会出现编译错误,不能调用外部类非静态成员方法 } } } // class InnerClasss_Static{ // // }