Java 随笔

xiaoxiao2021-02-27  259

                                                                                                                       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会在编译阶段为非静态的内部类的构造器增加一个参数,并且这个参数类型一定是外部类。调用这个构造器时要使用,否则就会爆运行时错误的。

转载请注明原文地址: https://www.6miu.com/read-3205.html

最新回复(0)