Java随笔简记-分模块记录
1:父,子类变量的访问过程:
类变量属于类本身情况就会简单很多的.
类变量是属于类本身总是在类加载的阶段完成初始化 实例变量属于java对象则在对象初始化阶段完成初始化
java也可以通过类变量来访问对象
子类定义一个类变量,这个子类的类变量会隐藏父类的类变量的,如果直接调用的话就是子类的,这叫做就近原则.
class StaticSubPar{ //父类定义一个类变量 static int count=20; } public class StaticSub extends StaticSubPar { //子类定义一个类变量,这个子类的类变量会隐藏父类的类变量的,如果直接调用的话就是子类的,这叫做就近原则 static int count=30; @SuppressWarnings("static-access") public void info(){ System.out.println("访问本地的类变量:"+count); //1:这里使用父类的类名作为主调访问count的类变量 System.out.println("访问父类的类变量:"+super.count); //2:这里通过super限定名来访问count的类变量 //两种方法都可以但是建议使用第一种,因为类变量本生就属于类本身,使用类名来主调访问类变量总是可以保证良好的代码可读性. System.out.println("访问父类的类变量:"+StaticSubPar.count); } public static void main(String[] args) { StaticSub sub=new StaticSub(); sub.info(); } }
运行结果:
访问本地的类变量:30 访问父类的类变量:20 访问父类的类变量:20
2:成员内部类 (member inner classes)
Q:为啥使用内部类呐?
A:内部类提供了更好的封装,可以无需实例对象就可以直接访问外部的私有变量,包括:(非静态的私有变量,静态的私有变量,非静态的私有方法,静态的私有方法)
成员内部类可以访问外部类的静态与非静态的方法和成员变量。
内部类可以直接访问外部类的私有变量,提供更好的封装 member inner classes(成员内部类)
测试代码: class StaticSubPar{ //1:非静态的私有变量 private int count=20; //2:静态的私有变量 private static int grade=80; //3:非静态的私有方法 private void testPar(){ System.out.println("测试父类的非静态私有方法"); } //4:静态的私有方法 private static void teststaticPar(){ System.out.println("测试父类的静态私有方法"); } public class StaticSubSon{ public void test(){ System.out.println(count); System.out.println(grade); testPar(); teststaticPar(); } } } public class StaticSub { public static void main(String[] args) { StaticSubPar.StaticSubSon s=new StaticSubPar().new StaticSubSon(); s.test(); } }
运行结果:
20 80 测试父类的非静态私有方法 测试父类的静态私有方法
3:非静态内部类的小陷阱:()
Q:非静态的内部类不容许有静态的成员的吗?
A:因为非静态的内部类本身就是一个非静态的上下文环境了,就自然不容许有静态的成员了.
非静态的内部类创建实例的陷阱:
public class Outer { private void test() throws InstantiationException, IllegalAccessException{ //创建非静态内部类的对象 //1:使用new的方式,调用构造方法 System.out.println(new Inner()); //2:反射调用,不调用构造方法 System.out.println(Inner.class.newInstance()); } //这里定义一个非静态的内部类 public class Inner{ public Inner(){ System.out.println("非静态的内部类的构造方法"); } public String toString(){ return "返回一个内部类的对象!"; } } public static void main(String[] args) throws InstantiationException, IllegalAccessException { new Outer().test();; } }
运行结果:
非静态的内部类的构造方法 返回一个内部类的对象! Exception in thread "main" java.lang.InstantiationException: com.lx.TestStaticSub.Outer$Inner at java.lang.Class.newInstance(Class.java:427) at com.lx.TestStaticSub.Outer.test(Outer.java:8) at com.lx.TestStaticSub.Outer.main(Outer.java:20) Caused by: java.lang.NoSuchMethodException: com.lx.TestStaticSub.Outer$Inner.<init>() at java.lang.Class.getConstructor0(Class.java:3082) at java.lang.Class.newInstance(Class.java:412) ... 2 more
分析这个运行结果:
public Outer$Inner(Outer)
会发现两种的创建Inner实例方法中通过new调用构造器初始化的方式是可以成功的,但是通过反射就报错了。
非静态的内部类Inner没有无参数的构造器,他构造器需要一个Outer参数的,非静态的 内部类的规则就是:
非静态的内部类需要寄生在外部类的实例中的,没有外部类的对象就不会有一个内部类的对象的。就算是程序中显示的提供一个非静态内部类的无参数的构造方法,这个无参数的构造方法依然需要一个外部类的形参。
从第一种方法来看,程序是显示的调用Inner无参数的构造方法创建实例的,但是虚拟机底层会传一个this到Inner的构造器里的,这个this就是当前的外部类Outer对象实例作为实参数的。
而程序通过反射就会指定Inner内部类的无参数构造器, Caused by: java.lang.NoSuchMethodException:
JVM会在编译阶段为非静态的内部类的构造器增加一个参数,并且这个参数类型一定是外部类。调用这个构造器时要使用,否则就会爆运行时错误的。