什么是内部类?为什么要使用内部类?
内部类是指在类的内部可以定义另一个类。内部类可以申明成public或private,其访问权限和成员变量和成员方法完全相同。
额外补充:
访问控制符的权限
private | default | proteced | public | |
---|---|---|---|---|
同一类 | ✅ | ✅ | ✅ | ✅ |
同一包中的类 | ❌ | ✅ | ✅ | ✅ |
不同包中的子类 | ❌ | ❌ | ✅ | ✅ |
其他包中的类 | ❌ | ❌ | ❌ | ✅ |
使用内部类的主要原因:
- 内部类方法可以访问该类定义所在作用域中的数据,包括私有的数据。
- 内部类可以对同一包中的其他类隐藏起来。
- 当想要定义一个回调函数且不想编写大量代码时,使用匿名内部类比较便捷。
内部类的定义格式
public class OuterAndInner {
private String name;
private int age;
public class innerClass{
private String grade;
private String classes;
}
}
内部类可以直接访问外部类的元素,但是外部类不可以直接访问内部类的元素。
package outerAndInner;
public class OuterAndInner {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public OuterAndInner(String name, int age) {
super();
this.name = name;
this.age = age;
}
public class innerClass{
private String doSomeThing;
public String getDoSomeThing() {
return doSomeThing;
}
public innerClass(String doSomeThing) {
super();
this.doSomeThing = doSomeThing;
}
public void setDoSomeThing(String doSomeThing) {
this.doSomeThing = doSomeThing;
}
public void infor() {
System.out.println("我的名字是 "+ name +", 今年 "+age +",现在正在 "+doSomeThing);
}
}
public static void main(String[] args) {
OuterAndInner outerAndInner = new OuterAndInner("琪琪", 18);
OuterAndInner.innerClass innerClass = outerAndInner.new innerClass("参加高考");//调用内部类中的方法
innerClass.infor();
}
}
通过以上的示例可以看出内部类可以直接访问外部类属性,尽管外部类属性是用private修饰的。
内部类的特殊语法规则
OutClass.this:表示外围类的引用
outObject.new InnerClass(××);内部对象构造器
OutClass.InnerClass:引用内部类。
四种内部类
1)静态内部类
- 必须以static关键字修饰
- 用static修饰的内部类不能访问非static修饰的外部类的成员变量和方法。
- 不能直接实例化内部类,要通过外部类来实例化内部类:
OuterClass.innerClass inter = new outerClass.innerClass(); - 静态内部类中可以定义静态或者非静态的成员
e.g.
package outerAndInner;
public class StaticOuter {
private static String name = "岳岳";
private int age;
public void getInfo() {
staticInnerClass innerClass = new staticInnerClass();
innerClass.staticInner("参加面试");//调用静态内部类中的方法
}
/**静态内部类*/
public static class staticInnerClass{
public static void staticInner(String donthing) {
System.out.println(name +"现在正在" + donthing);
}
}
public static void main(String[] args) {
StaticOuter outer = new StaticOuter();
outer.getInfo();
}
}
由以上例子可以得出:今天内部类中不能调用非静态的外部成员变量或方法。当然也可以在方法中第一内部类的,这里例子就省略了。
2)成员内部类
成员内部类中不能定义静态变量和方法,但是可以访问外部类中的所有成员。如果外部类想要访问内部类中的成员和方法,可以通过实例化来实现。
e.g.
package outerAndInner;
public class MemberOuter {
private String name ;
private static int age;
public void outerMethod() {
System.out.println("(⊙v⊙),这个是外部方法");
}
public class MemberInner{
public void innerMethod() {
name = "琪琪";
age = 23;//直接使用外部成员变量
System.out.println("内部输出: "+name+" , 今年 "+age +"岁");
outerMethod();//直接使用外部成员方法。
}
}
public static void main(String[] args) {
MemberOuter memberOuter = new MemberOuter();
MemberOuter.MemberInner memberInner = memberOuter.new MemberInner();//实例化访问内部类的方法
memberInner.innerMethod();
}
}
3)局部内部类
如果一个内部类只在一个方法中使用到了,那么我们可以将这个类定义在方法内部,这种内部类被称为局部内部类。其作用域仅限于该方法。
注意:
1) 局部内类不允许public ,private ,protected 访问权限修饰符进行申明。
2)局部内部类对外部世界可以完全地隐藏起来。
3)局部内部类不仅可以访问包含它们的外部类,还可以访问用final申明的局部变量,但是不可定义静态变量。
e.g.
package outerAndInner;
public class LocalOuter {
private String name;
private int age;
public void OuterClass(){
System.out.println("这是一个外部方法");
class LocalInner{
String address = "成都市双流区";
public void InnerClass(final String donthings) {
System.out.println("这是一个在外部方法中定义的一个局部内部类");
name = "琪琪";
age = 23;//直接使用外部成员变量
System.out.println("内部输出: "+name+" , 今年 "+age +"岁,现在在 "+address+","+donthings);
System.out.println(this.address);//用"this.变量名" 访问内部类变量
System.out.println(LocalOuter.this.name);//用外部"外部类类名.this.变量名" 访问外部类变量
}
}
LocalInner localInner = new LocalInner();
localInner.InnerClass("正在码代码");
}
public static void main(String[] args) {
LocalOuter localOuter = new LocalOuter();
localOuter.OuterClass();
}
}
运行结果:
这是一个外部方法
这是一个在外部方法中定义的一个局部内部类
内部输出: 琪琪 , 今年 23岁,现在在 成都市双流区,正在码代码
成都市双流区
琪琪
4)匿名内部类
1) 匿名内部类是没有访问修饰符的。
2) 必须继承一个抽象类或者实现一个接口
3) 匿名内部类中不能存在任何静态成员或方法,因为匿名内部类属于局部内部类,所以局部内部类的所有限制都对匿名内部类有效。
4) 匿名内部类是没有构造方法的,因为它没有类名。
e.g.
package outerAndInner;
public class AnonymousOuter {
public InnerClass getInnerClass(final int age,String name){
// 继承一个抽象类或者实现一个接口
return new InnerClass() {
@Override
public String getinfo(){
return name + ",今年"+age +"岁";
}
};
}
public static void main(String[] args) {
AnonymousOuter anonymousOuter = new AnonymousOuter();
InnerClass innerClass = anonymousOuter.getInnerClass(23, "琪琪");
System.out.println(innerClass.getinfo());
}
}
//申明一个接口
interface InnerClass {
String getinfo();
}
总结不到位的地方,请各位多多指教