基本概念
内部类:是指把一个类的声明放到另一个类的声明中,甚至是放到一个方法内部,这样的类称为 内部类。
内部类分为 命名内部类和匿名内部类:
- 命名内部类:就像平时声明一个类一样,有个名字。只是放的位置是另一个类的内部或一个方法的内部。
- 匿名内部类:就是没有类名,一般将匿名内部类作为参数传递,也就是直接new 出某个类的子类或某个接口的实现类。两种内部类例子下面有
1、在内部类中可以访问它的外部类的所有数据成员和方法成员。通过 “OutterClass.this.” 来访问。
2、内部类中不能定义静态成员,凡是静态的都不可以定义。如果要static ,则同时必须是 final 的。
3、如果在外部类以外创建该内部类的实例,则必须先创建一个外部类的实例,然后再用这个外部类的实例对象创建内部类的实例对象。例子下面有。
4、类中的内部类的访问修饰符只能是public、protected、没有、private之一,好比在类中定义成员变量一样,还可加上abstract、final修饰符
- 如果内部类的访问修饰符是public的,那么在本包和其他包中的类均可访问。
- 如果内部类的访问修饰符是protected、或者没有访问修饰符的,那么只本包中的类才可访问。
- 如果内部类的访问修饰符是private的,那么就只能在外部类中访问。
5、方法中的内部类的访问修饰符只能是 没有,就好比在方法中定义局部变量一样,但可以加上abstract、final修饰符。
- 这种内部类只有在方法内部可见,其他任何地方均不可见。
- 这种内部类只有先定义再使用,类中的内部类无此限制,就好比方法中的局部变量必须先定义再使用是一样的。
- 这种内部类可以访问方法中的变量,但该变量必须是 final 的。
命名内部类 1:
package outterclass1;
/**
* 下面的代码也许毫无意义,这里只是讨论内部类而已。
*
*
*/
public class OutterClass {
private String name = "Outter Class Name";
// 下面这个InnerClass命名内部类,访问修饰符可以是public、protected、没有、 private
private class InnerClass {
private String name = "Inner Class Name";
/**
* 内部类中直接写this是指内部类,而如果先写 外部类名然后写this ,则能访问外部类的属性和方法。
*/
public void getOutterClassName() {
System.out.println(OutterClass.this.name);
}
/**
* 调用外部类的方法
*/
public void invokeOutterClassMethod() {
f();
}
/**
* 这里返回的是内部类的 name
*/
public String getName() {
return this.name;
}
}
// 在外部类中声明一个内部类类型的属性
private InnerClass ic = new InnerClass();
public void f() {
System.out.println("这是 OutterClass 的方法");
}
public void accessInnerClass() {
ic.invokeOutterClassMethod();
}
public InnerClass getIc() {
return ic;
}
/**
* 创建一个外部类对象,并获得内部类对象,然后通过内部类对象拿到外部类的name.
*
* @param args
*/
public static void main(String[] args) {
OutterClass oc = new OutterClass();
oc.getIc().getOutterClassName();//输出:Outter Class Name
}
}
命名内部类 2:
package outterclass2;
/**
* 我自己很少使用内部类,暂时还没有发现内部类在实际项目中发挥的作用,尤其是下面的方法中的内部类。
*
*
*/
public class OutterClass2 {
// 方法中的内部类的访问修饰符 :没有 、 abstract 、 final
public void f() {
String name = "temp variable name";
class InnerClass {
private String name = "Inner Class temp variable name";
public void getOutterName() {
System.out.println("怎么拿到上面那个name,我还真不知道,欢迎告知....");
}
}
InnerClass ic = new InnerClass();
ic.getOutterName();
}
public static void main(String[] args) {
OutterClass2 oc2 = new OutterClass2();
oc2.f(); // 输出:怎么拿到上面那个name,我还真不知道,欢迎告知....
}
}
匿名内部类 :
public class OutterClass{
/**
* 这里的参数可以是抽象类,具体类和接口
*/
public static void f(Exception e) {
e.printStackTrace();
}
//这里f的参数就是一个 匿名内部类,会立即创建一个该匿名内部类的对象
public static void testF() {
f(new Exception() {
@Override
public void printStackTrace() {
System.out.println("NND");
}
});
}
public static void main(String[] args) {
testF(); //输出 NND
}
}
在外部类以外的类中创建内部类的实例:
package outterclass2;
import outterclass1.OutterClass;
import outterclass1.OutterClass.InnerClass;
public class OutterClass3 {
public void f(){
OutterClass oc = new OutterClass();
InnerClass ic = oc.new InnerClass();
}
}
Static Nested Class
- 在类中定义的内部类,加上static修饰,就成了Static Nested Class
- 如果要访问外部类的成员,则该成员必须是 static 的。
- 在外部类以外的其他类中创建该 static nested class的对象,外部类的对象可以不创建。如:Outter.Inner inner = new Outter.Inner();
- Static Nested Class 中可以定义静态成员,不需要final修饰。与上述讲的内部类不一样。
- Static Nested Class 的访问修饰符只能是public、protected、没有、private之一,同时也可以有 abstract 、final 修饰符。也就是这个类可以同时被static和abstract修饰,这与abstract method不能同时被static 修饰是不一样的哦。
- 在静态方法中定义的内部类,也是 Static Nested Class
- 这种Static Nested Class的访问修饰符只能是 没有,但可以加上abstract、final修饰符。
- 如果要访问外部类的成员,则该成员必须是 static 的。
- 如果要访问方法内的成员变量,则必须要被 final 修饰。
- 这种Static Nested Class只有在方法内部可见,其他任何地方均不可见。
- 也必须先定义,才能使用。
- 这种Static Nested Class中不可以定义静态成员,凡是静态的都不可以。如果要static ,则同时必须是 final 的。
- 如果Static Nested Class的访问修饰符是public的,那么在本包和其他包中的类均访问。
- 如果Static Nested Class的访问修饰符是protected、或者没有访问修饰符的,那么只能在本包中的类访问。
- 如果Static Nested Class的访问修饰符是private的,那么就只能在外部类中访问。
好奇也试了哈,还可以在上述Static Nested Class 中继续定义类,类类,类的类的类。NND,我还是只想问这有何意义?
总结:
1、无论是类中的内部类,还是方法中的内部类,还是类中的Static Nested Class,还是静态方法中的Static Nested Class ,他们都可以被 abstract,final修饰。
2、无论是类中的内部类,还是类中的Static Nested Class,他们都可以被public、protected、没有、private之一修饰。
3、无论是方法中的内部类,还是静态方法中的Staitc Nested Class,他们的访问修饰符只能是 没有。
4、只有类中的Static Nested Class中才能定义静态成员,同时不需要被final修饰。在其他三个类中如果要定义static成员,则必须加上final修饰。
方法中的成员变量的访问修饰符只能是 没有,只能被 final 修饰。