何为内部类
java中,把一个类定义在另一个类的里面,或者方法里面,这样的类称为内部类。内部类可以随意访问外部类的任何成员,但是相反,外部类却不可随意访问内部类的成员,需要先实例化内部类方可调用。
内部类的分类
1.成员内部类
2.局部内部类
3.匿名内部类
4.静态内部类
成员内部类
成员内部类定义与一个类的里面,大概样子如下所示
public class Outer {
public String outer ="outer";
//定以外部类方法
public void isOuter(){
System.out.println(outer);
}
//定义内部类
class Inner{
public String inner ="inner";
public void isInner(){
System.out.println(inner);
}
}
}
可以看到内部类Class Inner定义在外部类Class Outer的里面,为了证实刚才的结论,我作出了一些调用
可以清楚看到,内部类可以直接调用外部类的任何成员(包括private修饰);而外部类要访问内部成员的话就必须要先实例化;
如图实例化后,外部类就可以正常调用内部类的成员(测试的时候注意注释掉一些互相调用的代码,以免造成死循环)
除了通过上面的那种通过return new Inner()完成实例化,还有一种方式
Outer out = new Outer();
Inner in = out.new Inner();
//或者这样
Outer.Inner in2 = out.new Inner();
而内部成员类可以使用任何的修饰符,如同private
所以两种实例化该怎么使用要看个人的需求了
局部内部类
局部内部类就是一个定义在一个方法里,或者定于在一个作用域了,跟普通类的局部变量非常类似,通过的,局部内部类一样不能有访问修饰符,它大体的样子大概是这样的:
public class OuterMethod {
public String outer ="outer";
private String outerPr = "outerPr";
//这是外部类的方法
public void whatInner(){
String outMethodMember = "局部变量";
//定以局部内部类
class MethodInner{
//定以局部内部类的方法
public void isInner(){
System.out.println("Inner");
}
}
}
}
访问修饰符都不能有,以及内部类的成员不能有static,但是他们可以拥有访问修饰符和final
这里的原因我估摸着虚拟机加载时,会把static修饰的成员都先加载了,就像平时可以直接调用static方法和变量一样,而局部内部类,是需要在外部类实例化后,再对内部类实例化,里面的成员才会开始加载,与当初定以static的目的不一致,具体的我也不是特别清楚为什么了…
匿名内部类
匿名内部类和局部内部类很相似,不过匿名内部类的写法更为简便,省去了起类名的过程。不过匿名内部类的使用有一个前提:要继承父类或者实现接口
匿名内部类极大的方便了我们的编写,例如我们的Thread
public class Threads extends Thread{
//正常创建类
@Override
public void run() {
for(int i=0;i<10;i++){
System.out.println(this.getName());
}
}
public static void main(String[] args) {
Threads t1 = new Threads();
Threads t2 = new Threads();
t1.setName("t1");
t2.setName("t2");
t1.start();
t2.start();
}
//匿名内部类创建
public static void main(String[] args) {
new Thread(){
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println("t1");
}
}
}.start();
new Thread(){
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println("t2");
}
}
}.start();
}
}
因为代码简单的原因,差距并没有体现出来,但是可以看到,普通创建的话需要起一个类似于 t1 , t2 等这类名字,匿名内部类就可以省去了。可能因为这样,在JDK1.8之后推出了Lambda表达式,真的是把java代码简洁到了极致的一个程度,大家可以去了解下这个Lambda
静态内部类
静态内部类,顾名思义就是在内部类上加了static关键词修饰。一旦内部类使用static修饰,那么此时这个内部类就升级为顶级类。静态内部类是不需要依赖于外部类的,并且它不能使用非static成员变量或者方法,不管外部还是内部
public class OuterStatic {
public String outer ="outer";
public static String outerstaic = "out";
private String outerPr = "outerPr";
private static class Inner{
public static String inner ="inner";
private String innerPr = "innerPr";
public static void isInner(){
System.out.println(inner);
//无法使用
System.out.println(innerPr);
System.out.println(outerPr);
}
}
public static void main(String[] args) {
Inner inner = new Inner();
//out.isOuter();
inner.isInner();
}
}
可以看到,可以直接不通过外部类,直接实例化一个静态内部类,或者我们可以按照调用外部类的静态成员一样,直接调用
OuterStatic.Inner.isInner();
内部类是JAVA很重要的一个环节:
(1)极大的增强了java代码的灵活性,
(2)它可以有效地对外界隐藏起来自己
(3)可以解决java单继承的缺点,即使外部类继承了其他父类,也不会影响内部类的继承