gitee代码地址:https://gitee.com/mixMi/JavaSE-self-study/tree/master/inner-class/src
一,何为内部类
在Java中,可以将一个类定义在另一个类里面或者一个方法里面,这样的类称为内部类。广泛意义上的内部类一般分为四种:
成员内部类
局部内部类
匿名内部类
静态内部类
二,成员内部类
成员内部类是最普通的内部类,它是外部类的一个成员。
内部类实例创建:通过外部类的实例去创建(推荐使用getInstance的方法去创建)
访问外部的权限:无限制访问外部类的所有属性和方法(包括private修饰的)
外部访问的权限:需要通过内部类的实例去访问
public class Outter {
private String name = "outter";
private static String property = "p";
public Inner getInnerClass(){
return new Inner();
}
public class Inner{
public String name = "inner";
public void innerSay(){
String name = "innerMethod";
System.out.println(name);//命名冲突时,会找最近的
System.out.println(this.name);//this代表本内部类
System.out.println(Outter.this.name);//命名冲突时要调用外部类成员,用Outter.this
System.out.println(property);//可以任意访问外部类任意成员或方法
}
}
}
public class Test {
public static void main(String[] args) {
Outter out = new Outter();
Outter.Inner inner = out.getInnerClass();//推荐使用
//Outter.Inner inner = out.new Inner(); //或者也可用外部类实例去创建
inner.innerSay();
}
}
//运行结果
innerMethod
inner
outter
p
使用注意:
1,成员内部类中不能存在任何static属性和方法
2,成员内部类的访问控制符可以用public、protected、private等
3,在外部类的外部不能直接去new一个成员内部类,必须使用外部类对象来创建,即 外部类对象.new 内部类();
4,如果外部类和成员内部类有命名相同的成员变量或方法,内部成员类默认访问自己的成员变量或方法,如果要访问外部类的成员变量或方法,需要用 外部类.class来调用
三,局部内部类
局部内部类被定义在方法或作用域内,只对由该方法或作用域可见,即只能被该方法或作用域调用。
内部类实例创建:只能在作用域内创建
访问外部的权限:无限制访问外部类的所有属性和方法(包括private修饰的)
外部访问的权限:只能通过该方法或作用域交互
public class Outter {
private String name = "outter";
public void display(){
String name = "method"; //暂时没有找到访问此属性的方式
class Inner{
String name = "inner";
public void say(){
String name = "innerSayMethod";
System.out.println(name);
System.out.println(this.name);
System.out.println(Outter.this.name);
}
}
Inner inner = new Inner();
inner.name = "changeName";
inner.say();
}
}
public class Test {
public static void main(String[] args) {
Outter outter = new Outter();
outter.display();
}
}
//运行结果
innerSayMethod
inner
outter
使用注意:
1,由于局部内部类只能被该方法或作用域调用,所以不能用访问控制符和static修饰局部内部类
局部内部类中的display()方法中定义的String name = "method"变量我暂时没有找到访问的方法,有知道的小伙伴请在评论里告诉我,感激不尽
四,匿名内部类
匿名内部类应该是我们平时用的最多的内部类,它是一个没有名称的类,先看下面这个监听器例子:
button2.addActionListener(
new ActionListener(){
public void actionPerformed(ActionEvent e) {
System.out.println("你按了按钮二");
}
});
上面的添加监听事件的写法就是标准的匿名内部类,但是我们为什么要这么写呢。回忆一下我们在学习接口和抽象类时候的demo,例如,定义一个Animal的接口或抽象类,给它定义一个eat()的方法,然后实现一个猫和一条狗的eat()。我们用常规写法的话,至少需要3个类,即Animal、Dog和Cat。但我们写成匿名内部类的话,代码就会这样:
public abstract class Animal {
abstract void eat();
}
public class Test {
public static void main(String[] args) {
Animal cat = new Animal() {
@Override
void eat() {
System.out.println("猫吃鱼");
}
};
cat.eat();
Animal dog = new Animal() {
@Override
void eat() {
System.out.println("狗吃。。。");
}
};
dog.eat();
}
}
会发现我们只需要写一个类就够了(即 只写Animal,Dog和Cat在需要它们的时候再写),上例是抽象类的写法,接口的写法也类似。
使用注意:
1,使用匿名类时,我们必须是继承一个类或实现一个接口(上例中的dog和cat实际上就是继承了Animal类),但二者不可同时存在,同时也只能继承一个类或实现一个接口;
2,匿名内部类中不能定义构造函数;
3,匿名内部类中不能存在static修饰的成员和方法;
4,匿名内部类是局部内部类的一种,所以局部内部类的限制同样对匿名内部类生效;
5,匿名内部类不能是抽象的,它必须要实现继承的类或实现的接口的所有抽象方法
6,如果一个匿名内部类在方法中被声明,那么可以利用这个方法去传入你想要在匿名内部类中使用的参数,但是这些参数必须被final修饰,详细解释请看 JavaSE(二)内部类问题详解
五,静态内部类
被static修饰的内部类就是静态内部类,根据静态内容的加载顺序,我们可以得出以下结论:
1,静态内部类的创建不需要依靠外部类对象
2,静态内部类不能直接访问外部类的任何非static成员变量和方法(可以用 new 外部类().成员 的方式访问)
3,外部类的静态成员或在静态内部类中没有名字冲突时,静态内部类可直接调用
public class Outter {
private String name = "outter";
private static int age = 13;
public static class Inner{
String myName = "inner";
public static void staticDisplay(){
System.out.println(new Outter().name);
System.out.println(age);
}
public void display(){
System.out.println(myName);
}
}
}
public class Test {
public static void main(String[] args) {
Outter.Inner.staticDisplay();
Outter.Inner inner = new Outter.Inner();
inner.display();
}
}
//运行结果
outter
13
inner