标签:编译 can public 实例变量 静态 oracl 创建 非静态内部类 hashmap
如果你是一个急性子,没什么耐性的人,可以只看下句,自己去品味理解:
内部类:就是我是你的一部分,我了解你,我知道你的全部,没有你就没有我。(所以内部类对象是以外部类对象存在为前提的)
静态内部类:就是我跟你没关系,自己可以完全独立存在,但是我就借你的壳用一下,来隐藏自己。
如果还不知道静态和普通成员的区别,就先学static吧。
静态成员:属于这个类,数据存放在class文件中,程序运行之前就已经存进去数据了。
普通成员:属于这个类的对象,程序运行后生成堆栈中。
先来看一下官方说法,根据Oracle官方的说法:
Terminology: Nested classes are divided into two categories: static and non-static. Nested classes that are declared static
are called static nested classes. Non-static nested classes are called inner classes.
一个称为静态嵌套类(静态内部类),一个称为内部类。那么两者到底有什么区别呢?很多JDK源码用到了静态内部类。HashMap、ThreadLocal、AQS的sync等。那么接下来学习一下内部类吧!
内部类是定义在另外一个类中的类,主要原因有:
静态内部类和非静态内部类最大的区别是:非静态内部类编译后隐式保存着外部类的引用(就算外部类对象没用了也GC不掉),但是静态内部类没有。
内部类定义语法格式如下:
class OuterClass { ... class NestedClass { ... } }
我们直接先看来一个例子吧,在Human类里定义了一个HumanLeg非静态内部类,并且在HumanLeg类的实例方法中直接访问外部类的private访问权限的实例变量和类变量。
/** * 人类 - 外部类 * * @author GrimMjx */ public class Human { private static final int eyes = 2; private static void count() { System.out.println("I can count number"); } private int teeth = 10; private void say() { System.out.println("Hello world"); } /** * 人腿 - 非静态内部类 */ public class HumanLeg { private Double length; public HumanLeg(Double length) { this.length = length; } public void test() { say(); count(); System.out.println("I have " + eyes + " eyes"); System.out.println("I have " + teeth + " teeth"); System.out.println("My leg has " + length.toString() + "cm long"); } } public static void main(String[] args) { Human human = new Human(); HumanLeg humanLeg = human.new HumanLeg(100D); humanLeg.test(); } }
运行结果:
Hello world I can count number I have 2 eyes I have 10 teeth My leg has 100.0cm long
由此看出,非静态内部类可以直接访问外部类的实例变量、类变量、实例方法、类方法。这是因为在非静态内部类对象里,保存了一个它所寄生的外部类对象的引用(非静态内部类实例必须寄生在外部类实例里)。也就是说,非静态内部类对象总有一个隐式引用,指向了创建它的外部类对象。我们来画一张示意图来理解一下。
另外,还有一些要注意的点
/** * @author GrimMjx */ public class Test { class Inner{ static { } } // 静态成员无法访问非静态成员 public static void main(String[] args) { new Inner(); } }
如果非静态内部类方法访问某个变量,其顺序为
接下来看一个例子:
/** * @author GrimMjx */ public class Outer { private int i = 1; public class Inner { private int i = 2; public void print() { int i = 3; System.out.println(i); System.out.println(this.i); System.out.println(Outer.this.i); } } public static void main(String[] args) { Outer outer = new Outer(); Inner inner = outer.new Inner(); inner.print(); } }
运行结果:
3 2 1
如果用static来修饰一个内部类,那么就是静态内部类。这个内部类属于外部类本身,但是不属于外部类的任何对象。因此使用static修饰的内部类称为静态内部类。静态内部类有如下规则:
/** * 静态内部类测试外部类。 * * @author GrimMjx */ public class StaticInnerTest { 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(x); System.out.println(y); } } public static void main(String[] args) { StaticInnerTest staticInnerTest = new StaticInnerTest(); staticInnerTest.test(); InnerClass innerClass = new InnerClass(); innerClass.test(); } }
标签:编译 can public 实例变量 静态 oracl 创建 非静态内部类 hashmap
原文地址:https://www.cnblogs.com/GrimMjx/p/10105626.html