Dog dog = new Dog();我们总是习惯于固定语句的执行,却对于背后的实现过程缺乏认知,而理解这个过程对后面晦涩难懂的反射和代理其实会有很大帮助,所以请务必学好这块内容。
堆内存:存放创建的对象和数组,会由java虚拟机的自动垃圾回收来管理(GC),创建一个对象放入堆内的同时也会在栈中创建一个指向该对象堆内存中的地址引用变量,下面说的对象就是存在该内存中
/** * * 堆代码 duidaima.com * 执行顺序:(优先级从高到低。)静态代码块>构造代码块>构造方法>普通方法。 * 其中静态代码块只执行一次。构造代码块在每次创建对象是都会执行。 */ public class Dog { //默认狗狗的最大年龄是16岁 private static int dog_max_age = 16; //狗狗的名字 private String dog_name; { System.out.println("狗狗的构造代码块"); } static { System.out.println("狗狗的静态代码块"); } //无参构造器故意没设 //有参构造器 public Dog(String dog_name) { this.dog_name = dog_name; } public void getDogInfo(){ System.out.println("名字是:"+dog_name + " 年龄:" + dog_max_age); } //狗叫 public static void barking(){ System.out.println("汪汪汪~~~"); } }
//以下操作只能由jvm完成,我们手动做不了 Class cls1 = new Class(Dog.class.getClassLoader()); Class cls2 = new Class(Cat.class.getClassLoader()); Class cls3 = new Class(People.class.getClassLoader());
@CallerSensitive public T newInstance() throws InstantiationException, IllegalAccessException { if (System.getSecurityManager() != null) { checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), false); } if (cachedConstructor == null) { if (this == Class.class) { throw new IllegalAccessException( "Can not call newInstance() on the Class for java.lang.Class" ); } try { Class<?>[] empty = {}; //声明无参构造对象 final Constructor<T> c = getConstructor0(empty, Member.DECLARED); // Disable accessibility checks on the constructor // since we have to do the security check here anyway // (the stack depth is wrong for the Constructor's // security check to work) java.security.AccessController.doPrivileged( new java.security.PrivilegedAction<Void>() { public Void run() { c.setAccessible(true); return null; } }); cachedConstructor = c; } catch (NoSuchMethodException e) { //如果class中没有无参构造方法,那么抛InstantiationException错误 throw (InstantiationException) new InstantiationException(getName()).initCause(e); } } Constructor<T> tmpConstructor = cachedConstructor; // Security check (same as in java.lang.reflect.Constructor) int modifiers = tmpConstructor.getModifiers(); if (!Reflection.quickCheckMemberAccess(this, modifiers)) { Class<?> caller = Reflection.getCallerClass(); if (newInstanceCallerCache != caller) { Reflection.ensureMemberAccess(caller, this, null, modifiers); newInstanceCallerCache = caller; } } // Run constructor try { //最终还是调用了无参构造器对象的newInstance方法 return tmpConstructor.newInstance((Object[])null); } catch (InvocationTargetException e) { Unsafe.getUnsafe().throwException(e.getTargetException()); // Not reached return null; } }首先搞清楚 newInstance 两种方法区别:
//Dog类中只有一个dog_name的有参构造方法 Class c = Class.forName("com.service.ClassAnalysis.Dog"); Dog dog = (Dog) c.newInstance();//直接抛InstantiationException异常
//Dog类中只有一个dog_name的有参构造方法 Constructor cs = Dog.class.getConstructor(String.class); Dog dog = (Dog) cs.newInstance("小黑");//执行没有问题但是这里面的 newInstance跟我们这次要说的 new 方法存在区别,两者创建对象的方式不同,创建条件也不同:
Dog dog1 = new Dog("旺财"); Dog dog2 = new Dog("小黑"); Class c = Class.forName("com.service.classload.Dog");//为了测试,加了无参构造 Dog dog3 = (Dog) c.newInstance(); System.out.println(dog1.getClass() == dog2.getClass()); System.out.println(dog1.getClass() == dog3.getClass());
public static int i = 666;//被类加载器加载到内存时会执行,赋予一个初始值 public static Integer ii = new Integer(666);//也被赋值一个初始值但请注意,实际上i 的初始值是0,不是666,其他基本数据类型比如boolean的初始值就是false,以此类推。如果是引用类型的成员变量 ii 那么初始值就是null。
Dog dog = new Dog("旺财");//在这里打个断点执行,首先会执行静态成员变量初始化,默认值是0:
static { System.out.println("狗狗的静态代码块"); }到这为止,类的加载过程才算完成。
3.对象实例化完毕后如果存在引用对象的话还需要把第一步的栈对象指向到堆内存中的实际对象,这样一个真正可用的对象才被创建出来。