Java 随笔

来源:互联网 发布:静音键盘推荐知乎 编辑:程序博客网 时间:2024/04/28 14:36

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

0 0