一、内部类基础
广发意义上来讲分为:成员内部类、局部内部类、匿名内部类、静态内部类。
1、成员内部类
成员内部类可以无条件的访问外部类的成员属性和方法。包括private成员和static成员。
需要特别说明的当内部类的成员和外部内的成员同名时会发生隐蔽,访问外部类同名成员的方法:
外部类.this.外部成员(变量或方法)。
外部类访问内部类的成员必须先创建一个内部类的对象。
/**
* 内部类
*
* @author wangmaoyu
* @create 2018-06-05 0:27
**/
public class Circle {
private int length=1;
private static double count=2;
public Circle(){
getInnerInstance().test(); //外部类访问内部类的成员必须先创建一个内部类的对象。
}
public Inner getInnerInstance(){
return new Inner();
}
class Inner{
private int length=3;
public void test(){ //内部类
System.out.println(length); //访问外部类私有成员
System.out.println(Circle.this.length); //访问外部类私有成员(外部类的成员同名的话,访问方式:外部类.this.成员(变量或方法)
System.out.println(count); //访问外部类静态成员
}
}
public static void main(String[] args) {
Circle circle = new Circle();
Inner inner = circle.new Inner();
inner.test();
}
}
内部类可以拥有private访问权限、protected访问权限、public访问权限及包访问权限。比如上面的例子,如果成员内部类Inner用private修饰,则只能在外部类的内部访问,如果用public修饰,则任何地方都能访问;如果用protected修饰,则只能在同一个包下或者继承外部类的情况下访问;如果是默认访问权限,则只能在同一个包下访问。这一点和外部类有一点不一样,外部类只能被public和包访问两种权限修饰。我个人是这么理解的,由于成员内部类看起来像是外部类的一个成员,所以可以像类的成员一样拥有多种权限修饰。
2、局部内部类
定义在一个方法或作用域内,访问权限仅限于该方法体内或该作用域内。、
class People{
public People() {
}
}
class Man{
public Man(){
}
public People getWoman(){
class Woman extends People{ //局部内部类
int age =0;
}
return new Woman();
}
}
注意,局部内部类就像是方法里面的一个局部变量一样,是不能有public、protected、private以及static修饰符的。
3、匿名内部类
public class OuterClass {
public InnerClass getInnerClass(final int num,String str2){
return new InnerClass(){
int number = num + 3;
public int getNumber(){
return number;
}
}; /* 注意:分号不能省 */
}
public static void main(String[] args) {
OuterClass out = new OuterClass();
InnerClass inner = out.getInnerClass(2, "chenssy");
System.out.println(inner.getNumber());
}
}
interface InnerClass {
int getNumber();
}
注意:
- 匿名内部类没有访问修饰符。
- new 匿名内部类,这个类首先是要存在的。
- 当所在方法的形参需要被匿名内部类使用,那么这个形参就必须为final。
- 匿名内部类没有构造方法。
匿名内部类jdk8改造:
public class Outer {
public Inner getInner(final Integer num,String str){
/* return new Inner() {
@Override
public Integer getNumber() {
return num+3;
}
};*/
return ()->num+3; //jdk8函数式接口
}
public static void main(String[] args) {
Outer outer = new Outer();
System.out.println(outer.getInner(3,"yes").getNumber());
Supplier<Date> supplier=()-> new Date();
Date date=supplier.get();
System.out.println("当前时间:"+date);
}
}
4、静态内部类
静态内部类类似于外部类的静态成员,即成员内部类加上static修饰。静态内部类是不依赖于外部类的,也就说可以在不创建外部类对象的情况下创建内部类的对象。
二、使用场景和好处
- .每个内部类都能独立的继承一个接口的实现,所以无论外部类是否已经继承了某个(接口的)实现,对于内部类都没有影响。内部类使得多继承的解决方案变得完整。
- 方便将存在一定逻辑关系的类组织在一起,又可以对外界隐藏。
- 方便编写事件驱动程序。
- 方便编写事件驱动程序。