Terminology:
Nested classes are divided into 2 categories: static & non-static. Nested classes that are declared static are called static nested classes (静态嵌套类). Non-static classes are called inner classes.
0.简单总结 (quick scratch)
内部类:我是你的一部分,我了解你,知道你的全部(所有属性及方法),没有你就没有我。
( 因此内部类对象的创建依赖于外部类对象的存在)
静态内部类: 我和你没有关系,我可以独立于外部类对象存在,但是要借用你的壳子用一下,隐藏自己。
0.0 静态成员 vs 非静态成员
静态成员: 属于这个class,数据存放在class文件中,在程序运行时之前加载完成(数据已存放)
非静态成员: 属于这个class的对象,程序运行时生成在堆栈中。
1. 内部类
1.1 内部类定义
定义: 在一个类中定义并创建的类
语法:
class OuterClassA {
...
class NestedClassB {
...
}
}
1.2 内部类优势
- 内部类方法可以访问该类定义所在的作用域中的数据,包括了private成员
- 内部类可以对同一个package中的其他类不可见
与static nested class (静态内部类)最大区别:
非静态内部类编译后,隐式保留着外部类的引用,就算外部类对象不使用后也不会被GC,但是静态内部类不会
1.3 内部类例子
/ **
*
* Human类
*
* @author: RichardWWHH
*/
package learn.innerclasses;
public class Human {
private static final int eyes = 2;
private static void count() {
System.out.println("I can count");
}
private int teeth = 32;
private void say() {
System.out.println("Hello World");
}
/**
* HumanLeg类
*/
public class HumanLeg {
private Double legLength;
public HumanLeg(double legLength) {
this.legLength = legLength;
}
public void test() {
say();
count();
System.out.println("I am walking");
System.out.println("My leg is " + legLength.toString() + "cm Long");
}
}
public static void main(String[] args) {
Human human = new Human();
HumanLeg humanLeg = human.new HumanLeg(17.3);
humanLeg.test();
}
}
运行结果:
Hello World
I can count
I am walking
My leg is 17.3cm Long
Process finished with exit code 0
总结
非静态内部类可以访问 外部类的
- 实例变量,实例方法
- 类变量,类方法
正是由于非静态内部类对象保留了对外部类对象的引用。
或者说非静态内部类对象总是保留对外部类对象的隐式引用
⚠️注意:
- 外部类无法直接访问非静态内部类中的成员,除非实例化一个非静态内部类对象 (也就是说非静态内部类的成员只有非静态内部类可见)
- 由于static成员无法访问non-static成员这一规则:外部类的static方法无法访问non-static内部类成员
- 非静态内部类不允许定义静态成员 (1.没有意义 2.不符合逻辑)
/**
*
* @author RichardWWHH
*/
public class Test {
class Inner{
static {
}
}
// 静态成员无法访问非静态成员
public static void main(String[] args) {
new Inner();
}
}
⚠️内部类方法调用外部类成员变量
1.外部类中是否有该名字的成员变量 - 使用外部类的类名.this.变量名
例子:
package learn.innerclasses;
/**
* @author Richardwwhh
*/
public class Outer {
private int i = 1;
public class Inner {
private int i = 2;
public void print() {
int i = 3;
System.out.println(i);//方法中的变量i
System.out.println(this.i);//内部类中的变量i
System.out.println(Outer.this.i);//外部类中的变量i
}
}
public static void main(String[] args) {
Outer outer = new Outer();
Inner inner = outer.new Inner();
inner.print();
}
}
静态内部类
静态内部类定义
static修饰的内部类,就是静态内部类。这个内部类属于外部类本身,但不属于外部类的任何对象。
- 静态内部类不能访问外部类的实例成员,只能访问外部类的类成员
- 外部类可以使用静态内部类的类名作为调用者来访问静态内部类的类成员,也可以使用静态内部类对象访问其实例成员。
public class Outer {
private int x = 1;
private static int y = 2;
public void test() {
System.out.println(new InnerClass().a);//通过创建 内部类对象.属性名 访问
System.out.println(InnerClass.b);//通过 内部类.属性名 访问
}
static class InnerClass {
private int a = 3;
private static int b = 4;
public void test() {
//无法访问 内部类的
//System.out.println(a);
System.out.println(y);
}
}
public static void main() {
Outer outer = new Outer();
outer.test();
InnerClass inner = new InnerClass();//无需借助外部类 来 new
inner.test();
}
}
结果输出如下:
3
4
2
Process finished with exit code 0