定义:
内部类指的是在类的内部定义再定义一个类。
内部类仅仅是一个编译时的概念。Outer.java 中定义一个Inner.java ,编译成功后会生成两个完全不同的class文件,分别是 Outer.class 和 Outer$Inner.class , 所以内部类的名字完全可以和它的外部类名字相同。
内部类的分类:
- 成员内部类;
- 局部内部类;
- 匿名内部类;
- 静态内部类;
成员内部类:
成员的内部类是最常见的内部类,就是在外部类的基础上按照一般定义类的方式定义。
package inner;
public class Outer {
private int i;
public Outer(int i) {
super();
this.i = i;
}
public void privateInnerGetI() {
new PrivateInner().printI();
}
private class PrivateInner {
public void printI() {
System.out.println(i);
}
}
public class PublicInner {
private int i = 2;
public void printI() {
System.out.println(i);
}
}
public static void main(String[] args) {
Outer outer = new Outer(8);
outer.privateInnerGetI();//====8
PublicInner publicInner = outer.new PublicInner();
publicInner.printI();//====2
}
}
总结1、
1、成员内部类是依附外部类而存在的,如果要产生一个成员内部类,必须有一个外部类实例;
2、成员内部类中没有定义静态方法,不是例子中没有定义,而是成员内部类中不可以定义静态方法;
3、成员内部类可以声明为private , 声明为 private 的成员内部类对外不可见,外部不能调用私有成员内部类的public方法;
4、成员内部类可以声明为public , 声明为 public 的成员内部类对外可见,外部也可以调用共有成员内部类的public方法;
5、成员内部类可以访问其外部类的私有属性,如果成员内部类的属性和外部类的属性重名,则以成员内部类的属性为准;
局部内部类
局部内部类是定义在一个方法或者特定作用域里面的类;
package inner;
public class LocalClass {
private int j = 8;//外部成员并不是final
public void main1() {
int i = 1;//外部成员并不是final,其实是隐藏final,对于1.8以下的jdk一定要使用final修饰
class A{
public void print(){
System.out.println("" + i + j);//-->18 jdk1.8
System.out.println( i + j);//9
}
}
//方法内部new
A a = new A();
a.print();
}
public static void main(String[] args) {
LocalClass localClass = new LocalClass();
localClass.main1();
}
}
注意一下:
局部内部类没有修饰访问符,另外局部内部类要访问外部的变量或者对象,该变量或者对象的引用必须是用final修饰(1.8以下的jdk需要使用final修饰,1.8以上的不用显示修饰,但是也是有final修饰的,只不过隐藏了)。
匿名内部类
这个是内部类中使用最多的,因为方便,在多线程模块中的代码示例中大量使用了匿名内部类;
package inner;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class AnonymousClass {
public static void main(String[] args) throws InterruptedException {
List<String> list = Arrays.asList("HanMeiMei", "LiLei", "Tom");
Collections.sort(list, new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return o1.length() - o2.length();
}
});
System.out.println(list);
}
}
匿名内部类是唯一没有构造器的类,其使用范围很有限,一般都用于继承抽象类或实现接口(注意只能继承抽象类,不能继承普通类),匿名内部类Java自动为其起名为 XXX$1.class。
静态内部类
用static修饰的内部类就是静态内部类
package inner;
public class StaticClass {
private static int i = 1;//必须是static
public static class StaticInner{
public void notStaticPrint(){
System.out.println("StaticClass.StaticInner.notStaticPrint,i=" + i);
}
public static void staticPrint() {
System.out.println("StaticClass.StaticInner.notStaticPrint,i=" + i);
}
}
public static void main(String[] args) {
StaticClass.StaticInner staticInner= new StaticClass.StaticInner();
staticInner.notStaticPrint();
StaticClass.StaticInner.staticPrint();
}
}
总结4:
1、静态内部类中可以有静态方法,也可以有非静态方法;
2、静态内部类只能访问其外部类的静态成员与静态方法;
3、和普通方法一样,要访问静态内部类的静态方法,可以直接 “.” 出来 ,不需要一个实例;要访问静态内部类的非静态方法,必须拿到一个静态内部类的实例对象;
4、注意一下成员内部类和静态内部类实例化写法的区别;
- 成员内部类:
外部类.内部类 XXX = 外部类.new 内部类();
- 静态内部类:
外部类.内部类 XXX = new 外部类.内部类();
注意:局部内部类和匿名内部类只能访问final局部变量
被final修饰的变量相当于一个常量,编译时就可以确定并放在常量池中,最后去常量池中获取即可;
static 不可以修饰局部变量,因为static属于类是共享的而不是只属于某一个方法域;
使用内部类的好处:
1、Java允许实现多个接口,但不允许继承多个类,使用成员内部类可以解决Java不允许继承多个类的问题。在一个类的内部写一个成员内部类,可以让这个成员内部类继承某个原有的类,这个成员内部类又可以直接访问其外部类中的所有属性与方法,是不是相当于多继承了呢?
2、成员内部类可以直接访问其外部类的private属性,而新起一个外部类则必须通过setter/getter访问类的private属性
3、有些类明明知道程序中除了某个固定地方都不会再有别的地方用这个类了,为这个只用一次的类定义一个外部类显然没必要,所以可以定义一个局部内部类或者成员内部类,写一段代码用用就好了
4、内部类某种程度上来说有效地对外隐藏了自己,比如我们常用的开发工具Eclipse、MyEclipse,看代码一般用的都是Packge这个导航器,Package下只有.java文件,我们是看不到定义的内部类的.java文件的
5、使用内部类可以让类与类之间的逻辑上的联系更加紧密