Java对象创建的理解

200 阅读2分钟

java创建实例化对象有很多种方式,在大部分场景下我们用的都是new一个对象,首次接触到不是用new创建,大概是在JDBC那里用到了class.forname();今天我浅谈一下我对java创建对象相关知识的理解,仅个人理解

通过new创建一个对象

例:People people1=new People();

通过new的方式,我们可以调用类的无参或者有参构造方法来实例化出一个对象,JVM首先会去检查People这个符号所引用的类是否已被加载过,如果没有就会执行对应类的加载过程,在这里其加载过程就不做过多详述

通过反射创建一个对象

例:People people1=(People) Class.forName("全限定类名").newInstance();
   People people2=People.class.newInstance();

其实,不管是Class.forName()还是People.class都是为了获取这个类的class对象,在通过newInstance()方法来创建对象,但是这样创建使用的是类的无参构造方法来创建对象,若想更加灵活则可以通过 java.lang.relect.Constructor的newInstance()方法来进行创建

Constructor<?>[] constructors=People.class.getDeclaredConstructors();
People people1=(People)constructors[0].newInstance();

至于为什么要用反射来创建对象,其实主要涉及到了动态与静态的问题

静态编译:在编译时确定类型,绑定对象,既通过,类和类之间也因此有了关联,耦合度高.

动态编译:运行时确定类型,绑定类型.动态编译最大限度发挥了java的灵活性,体现了多态的应用,降低了类之间的耦合性

Class.forName和classloader的区别

在整个类的加载过程中分五个阶段:加载、验证、准备、解释、初始化.而classloader只负责第一步,而调用clinit方法,执行static方法以及给static变量赋值都是在初始化阶段完成的,所以并不会执行类中的静态代码块,而通过Class.forName则会执行static代码块.

当我们要加载资源时,可以通过Class.getResourceAsStream()或者Classloader.getResourceAsStream()来进行加载,二者也是有区别的,其实classloader主要是负责加载资源的,而之所以通过class也可以是因为 Class 类封装的 ClassLoader 的 getResourceAsStream() 方法,从 Class 类中的源码可以看出:

public InputStream getResourceAsStream(String name) {
        name = resolveName(name);
        ClassLoader cl = getClassLoader0();
        if (cl==null) {
            // A system class.
            return ClassLoader.getSystemResourceAsStream(name);
        }
        return cl.getResourceAsStream(name);
 }

之所以这样做无疑还是方便客户端的调用,省的每次获取ClassLoader才能加载资源文件的麻烦

那么Class.getResourceAsStream()和Classloader.getResourceAsStream()有什么区别 class.getClassLoader().getResourceAsStream(String name) 默认从classpath中找文件(文件放在resources目录下),name不能带"/",否则会抛空指针。采用相对路径, "/"就相当于当前进程的根目录,即项目根目录;

inStream = PropertiesTest.class.getClassLoader().getResourceAsStream("com/test/demo/test.properties");

class.getResourceAsStream(String name) 是采用绝对路径,绝对路径是相对于 classpath 根目录的路径,"/" 就代表着 classpath,所以 name 属性需要前面加上 "/";

inStream = PropertiesTest.class.getResourceAsStream("/com/test/demo/test.properties");