内部类:
在Java中的类一共分为以下几种:
①普通类:就是大家平时声明的类,定义时用public修饰和不用public修饰的类,用public修饰的在Java中只能有一个并且类名要和文件名相同。不用public修饰的类只能在同包中被调用,因为没有导入的包。
②抽象类:具有承载抽象方法能力的类,是对类的抽象。
③匿名类:抽象类在实例化对象的时候调用构造方法,会生成匿名类,匿名类要实现抽象类的所有抽像方法,所以抽象类即使有构造方法也不能实例化对象。
④外部类:内部类的外部类体,是用来承载内部类的载体。
⑤内部类:现在要来讨论我们今天的重点了,内部类。
在Java中内部类中可以有属性、方法、构造方法。在外部类中,可以调用内部类中的属性和方法(包括私有属性和私有方法),同时内部类也可以调用外部类中的属性和方法(包括私有属性和私有方法),内部类和外部类的关系其实是所属关系。其实把内部类看成是外部类的一个方法可能更好理解一些,在类中嘛,所以可以访问外部类的属性和方法,同时又属于外部类,则外部类又可以调用它的属性跟方法,这里要注意一个点,外部类调用内部类的属性和方法时要创建内部类的对象,而内部类调用外部类时直接调用即可。
例:
public class Test {
private int a = 1;
private int b = 2;
public class InTest{
private int c = 3;
private int d = 4;
public int add(){
return a + b; //调用外部类的私有属性,直接调用
}
private void printf(){
System.out.println("我是内部类的方法");
}
}
public void printf(){ //调用内部类的私有方法
InTest inTest = new InTest(); //调用内部类的方法时,要创建内部类的对象
inTest.printf();
inTest.add();
}
public int add(InTest inTest){
c + d; //外部类直接调用内部类的属性会报错
return inTest.c + inTest.d;
}
}
那么内部类在内存中的存储方式是怎样的呢,首先来讨论一下类是怎样加载的,所有的类模板其实都是Class的对象,在Java中jvm将类从外存中加载到内存时,将程序拆分成一个byte数组,此时在栈中创建一个Class类的对象名,同时在堆中开辟了一片内存空间,创建了一个 .class的对象。
public class Test {
int b;
public static void main(String[] args) throws IllegalAccessException, InstantiationException {
Class test = Test.class;
Test test1 = (Test) test.newInstance(); //创建Test的对象
Test test2 = new Test(); //直接创建一个Test的对象
System.out.println(test1.b);
System.out.println(test2.b);
}
}
类加载器先创建了一个Class的对象test,及为Test.class,然后调用test的newInstance()方法,创建了test1这个对象。test2是传统的创建对象的方式。
现在来看一下内部类的在内存中的存储方式:我们看到想要创建类,首先在堆中你要创建一个类模板,然后才能创建对象,内部类也是一个类嘛,他的类模板在外部类的对象里,所以要想创建内部类的对象,首先你要先有内部类的类模板吧,此时你就要创建一个外部类的对象才能有内部类的模板。如图所示:
public class TestIn {
public static void main(String[] args) {
Test.InTest t2 = new Test().new InTest();
t2.printf();
}
}
如图所示,先创建了一个外部类的对象,拿到InTest.class模板,然后才能创建内部类的对象,这样也可以解释了为什么创建内部类对象时要先创建外部类的对象。其实结合内存我们可以发现很多东西,比如静态的内部类,这里就不画图了,用代码实现一下就好了,其实和静态方法一样,外部类加载时就内部类加载到了元数据区,所以不用创建内部类模板了。如果不太懂可以参考我之前的博客,static和final的用法。下面是代码的实现:
public class TestIn {
public static void main(String[] args) {
Test.InTest t2 = new Test.InTest();
t2.printf();
}
}
今天就分享到这吧........