精华内容
下载资源
问答
  • instance方法
    千次阅读
    2019-12-05 15:30:17

    首先,什么是反射?

    概念:动态获取或者动态调用对象的方法  的功能我们称之为java语言的反射机制.

              为什么要用.class  ?

    举例:比如一只野外大象死亡。我们想要解剖它,查看大象的死因,以及其它属性(年龄、性别、心、肺、肝脏......)

              因为大象已经死亡,所以我们肉眼无法得知其体内“属性”,故而引入“反射”技术得到大象的信息。

              比如下面代码:

              
                   //获取Student类字节码对象
                    Class clazz = Class.forName("com.demo.Student");
                   
                    //通过公共的空参的构造方法创建对象
                    Object obj = clazz.newInstance();
                   
                    //获取公共的空参的构造方法
                    Constructor c = clazz.getConstructor();
                    Object obj = c.newInstance();
           
                    //获取私有的有参构造方法
                    Constructor c2 = clazz.getDeclaredConstructor(String.class,int.class);
                    //去除私有权限
                    c2.setAccessible(true);
                    //创建对象
                    Object obj = c2.newInstance("景甜",18);

    为什么要用newInstance()方法来创建对象?

    1.假设定义了一个接口Car,开始的时候开的是汽油车,定义为一个类OilCar,程序中这样写 OilCar  car= new OilCar() 。

    2.后来随着全球资源枯竭,国家政策支持的原因,换成了新能源电动汽车。此时定义一个类EnergyCar,程序写成: EnergyCar       car = new EnergyCar() 。

    3.如果后期汽车类型不断改变,每次都要改动,于是工厂模式出现了,而所有Car的实例都由CarFactory提供,这时如果再换一种车的时候,只需要把工厂的生产模式改一下。
     4. 而如果使用newInstance(),上面3的问题又可以轻松解决。具体方法是把Car的具体实现类的类名放到配置文件中,通过               newInstance()去生成实例。这样,改变另外一种Car的时候,只需要改下配置文件就可以了。

    代码如下:
    String className = “配置文件中Car的具体实现类的类名”;
    Car car = (Door) Class.forName(className).newInstance();
        如果再配合依赖注入的方法,就dada提高了软件的可伸缩性和可扩展性。

     

    更多相关内容
  • 在初始化一个类,生成一个实例的时候,newInstance()方法和new关键字除了一个是方法一个是关键字外,最主要的区别是创建对象的方式不同
  • 深入理解Constructor之newInstance方法

    千次阅读 2019-12-24 00:12:29
    知其然,知其所以然 0. 前言 在上一篇《反射从入门到精通之深入了解Class类》,我们深入分析了一下 ...调用无参构造函数:Class.newInstance() 调用带参数的构造函数: 通过 Class 类获取 Constructor 调...

    知其然,知其所以然

    0. 前言

    在上一篇《反射从入门到精通之深入了解Class类》,我们深入分析了一下 Class 类的原理。在本篇文章,我们分析一下 Constructor 使用方法的原理。

    1. Constructor

    通过反射调用构造函数有两种方法:

    • 调用无参构造函数:Class.newInstance()
    • 调用带参数的构造函数:
      • 通过 Class 类获取 Constructor
      • 调用 Constructor 中的 newInstance(Object … initarges) 方法

    具体可以详见《反射从0到入门》,知道了这些我们深入了解下 Constructor 中的 newInstance(Object … initarges) 方法。

    1.1 newInstance

    想要了解原理,第一步就是要看懂 jdk 的注释,newInstance 的注释如下:

    (打扰了,看不懂这个,全剧终。。。)

    别走,我来给你们翻译(Google 翻译真香)

    使用 Constructor 代表构造函数,根据参数创建并且初始化一个实例。各个参数将自动拆箱以匹配原始形式参数,并且原始参数和引用参数必须根据需要进行方法调用转换。

    要获取无参构造函数,参数长度可以为 0 或者是 null

    调用非静态内部类,参数该。。。(此处不翻译)

    访问通过并且参数检查成功,将继续进行实例化。如果构造函数的声明类没有初始化,需要初始化

    构造函数完成,返回新创建并且初始化好的实例

    根据小李这段粗糙的翻译中,可以得到下面几个关键的内容:

    • 根据参数创建初始化实例,参数有匹配的规则;
    • 获取无参构造函数,参数长度可以为 0 或者 null;
    • 有访问权限并且对参数进行检查,需要获取到构造函数的声明类;

    知道了这些我们来解读一下 newInstance() 的源码,看下图:

    源码可以拆分为三块:

    1. 校验权限:校验权限就不在此分析了,大家可以自行查看源码
    2. 获取构造函数的声明类
    3. 创建实体

    获取构造函数的声明类

    构造函数声明类 ConstructorAccessor 是一个接口,如下图所示:

    查看下接口的实现类如下结构(虚线代表实现接口,蓝色线代表继承,那白线是什么鬼?)

    从图中可知实现类都是继承了 ConstructorAccessorImpl 抽象类,并且实现了 newInstance() 方法。

    那到底使用哪个实现类那呢?咱们继续往下看

    如果 ConstructorAccessor 已经被创建了,获取并赋值。如果没有则通过 newConstructorAccessor 方法创建 ConstructorAccessornewConstructorAccessor 方法如下:

    newConstructorAccessor 分为三部分:

    1. 检查是否初始化

    这是反射工厂(ReflectionFactory)检查初始化状态,如果没有初始化会进行下面用红线圈上的操作。

    那大概猜一下这块是做什么呢?

    首先,inflation 字面理解是通胀或者膨胀,那 noInflation 按字面理解也是不膨胀。

    Threshold 字面理解是阈值,inflationThreshold 按字面理解是通胀阈值,就是一个通胀的界限值。

    按照字面理解可知 noInflation 来判断是否通胀,inflationThreshold 是一个通胀的界限值。

    问问度娘,验证下咱们的结果:

    JNI(Java Native Interface),通过使用 Java 本地接口书写程序,可以确保代码在不同的平台上方便移植。

    猜的差不多,JVM 有两种方法来访问有关反射的类的信息,可以使用 JNI 读取器或者 Java 字节码存取器。inflationThreshold 是使用 JNI 存取器的次数,值为 0 表示永不从 JNI 存取器读取。如果想强制使用 Java 字节码存取器,可以设置 noInflation 为 true。

    inflationThreshold 默认值是 15,如果不对 inflationThreshold 进行修改,JVM 访问反射的类的信息会先从 JNI 存取器读取 15次之后才会使用 Java 字节码存取器

    这就可以解释通为什么要有一个初始化检测的操作了。

    从这部分可以学到一些小知识:

    我们可以使用 -D= 来设置系统属性,通过 System.getProperty(“属性名称”) 来获取属性值。

    1. 获取当前类的 Class 实例

    1. 根据条件获取 ConstructorAccessor

      这么多 if 条件判断,不要慌,我来帮你分析一波:

      • 第 1 步,校验在第二步获取的 Class 实例是不是抽象类,如果是抽象类就抛出异常。
      • 第 2 步,判断是否是 Class 实例,因为 Class 实例的构造函数是 private,所以这块也需要抛出异常。
      • 第 3 步,判断这个 Class 实例是否继承 ConstructorAccessorImpl,如果是父子关系,就调用 BootstrapConstructorAccessorImpl 创建 ConstructorAccessor,这个方法是调用 native 方法,底层用 c++ 实现的本地接口。
      • 第 4 步,如果 noInflation 为 true 并且 Class 实例不是匿名的,需要调用 MethodAccessorGenerator.generateConstructor() 创建 ConstructorAccessor,具体的细节就不分析了,原理还是通过读取二进制文件,将 Class 实例加载进来,然后根据一些条件获取到想要的 Constructor
      • 第 5 步,上面的条件都不满足,就调用 NativeConstructorAccessorImpl,看下这个方法的源码:

      ​ 调用次数和 inflationThreshold 比较,如果大于inflationThreshold(默认是 15 次),调用的方法是不是和第四步是相同的。

      ​ 如果小于等于 inflationThreshold ,就要调用 newInstance0 方法,newInstance0 是 native 方法,调用的就是本地接口。

      ​ 其实第一步初始化的时候就是为了在这里做铺垫呢。

      ​ 到这里还没有完事,还有一个 DelegatingConstructorAccessorImpl 方法。

      ​ 那这一块使用了一手代理模式,把 NativeConstructorAccessorImpl 放入到 DelegatingConstructorAccessorImpl 的 delegate 中。newInstance 调用的是 delegate 的 newInstance 方法。

      ​ 还记得我最开始问白线是做什么的,这回解惑了吧。

    内容有点多,我画个图带你们梳理一下:

    图片链接

    创建实例

    上一步获取到了 ConstructorAccessor 的实现类,直接调用 newInstance 方法去创建实例。

    2. 总结

    我们回顾下前面的内容:

    首先我们根据 jdk 提供的注释知道 newInstance 可以根据参数进行初始化并返回实例,想要获取实例必须要获取到构造函数的声明类 ConstructorAccessor ,随后我们就深入分析了 ConstructorAccessor

    ConstructorAccessor 有一个抽象类 ConstructorAccessorImpl,其它的实现类需要继承 ConstructorAccessorImpl,分别是下面几个实现类:

    • InstantiationExceptionConstructorAccessorImpl:将异常信息存起来,调用 newInstance 会抛出 InstantiationException 异常。

    • BootstrapConstructorAccessorImpl:当需要创建的 Class 实例和 ConstructorAccessorImpl 是父子关系,就要返回 BootstrapConstructorAccessorImpl,调用的是底层的方法,通过 C++ 编写。

    • SerializationConstructorAccessorImpl:也是一个抽象类,当 JVM 从 Java字节码进行读取,会返回这个实现类。

    • NativeConstructorAccessorImpl:调用本地接口方法创建 ConstructorAccessor ,需要根据调用次数和inflationThreshold 做比较,inflationThreshold 的默认值是 15,可以通过**-Dsun.reflect.inflationThreshold=**来修改默认值。

      当调用次数大于 15次的时候,JVM 从 Java字节码进行获取。反之,从本地接口进行获取。

    • DelegatingConstructorAccessorImpl:代理类,是 NativeConstructorAccessorImpl 的父类。

    获取到了 ConstructorAccessor,通过调用 newInstance() 方法来创建实例。

    3. 彩蛋

    反射相关文章

    《反射从0到入门》

    《反射从入门到精通之深入了解Class类》

    公众号Java知识学堂,里面有我最近整理的反射相关内容,希望能对大家有所帮助。

    展开全文
  • newInstance方法

    千次阅读 2018-01-16 10:27:21
    Class.forName(String className)这个方法传入一个类型的全路径的名字(也就是带包的完整名字),会返回一个字节码类型(也...然后再用这个字节码类型的实例clazz调用newInstance()方法会返回一个Object类型的对象 如

    Class.forName(String className)这个方法传入一个类型的全路径的名字(也就是带包的完整名字),会返回一个字节码类型(也就是Class类型)的实例

    如:Class clazz = Class.forName("com.dean.Person");

    然后再用这个字节码类型的实例clazz调用newInstance()方法会返回一个Object类型的对象

    如下:Object object = clazz.newInstance();

    这个object当然不能直接调用Perosn类的方法了,因为他是Object类型

    这个时候就需要强制类型转换了

    Person person = (Perosn)clazz.newInstance();

    下面再解释一个加载数据库驱动时不用newInstance方法的原因:

    如下:

    Class.forName("com.mysql.jdbc.Driver");

    并没有写成:

    Driver driver = (Driver)Class.forName("com.mysql.jdbc.Driver").newInstance();

    DriverManager.registerDriver(driver);


    不过我再查看com.mysql.jdbc.Driver类的源码时发现了:

    static {
    try {
    java.sql.DriverManager.registerDriver(new Driver());
    } catch (SQLException E) {
    throw new RuntimeException("Can't register driver!");
    }
    }

    我的理解是这样的,当Class.forName("com.mysql.jdbc.Driver");被执行到时相当于com.mysql.jdbc.Driver的字节码实例被加载到内存了

    而按照类的初始化顺序静态代码块也应该被执行了,也就是说Class.forName("com.mysql.jdbc.Driver");看似一句实际上相当于下面两句

    Class.forName("com.mysql.jdbc.Driver");

    java.sql.DriverManager.registerDriver(new Driver());

    所以大多数jidbc连接代码写完Class.forName("com.mysql.jdbc.Driver");这句就去拿数据库连接了,几乎看不到注册驱动的代码。

    import java.sql.DriverManager;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.sql.Connection;
    import java.sql.Statement;
     
    public class MysqlDemo {
        public static void main(String[] args) throws Exception {
            Connection conn = null;
            String sql;
            //下面语句之前就要先创建javademo数据库
            String url = "jdbc:mysql://localhost:3306/javademo?"
                    + "user=root&password=root&useUnicode=true&characterEncoding=UTF8";
            try {
                //动态加载mysql驱动
                Class.forName("com.mysql.jdbc.Driver");
                System.out.println("成功加载MySQL驱动程序");
                //一个Connection代表一个数据库连接
                conn = DriverManager.getConnection(url);
                Statement stmt = conn.createStatement();
                sql = "create table student(NO char(20),name varchar(20),primary key(NO))";
                int result = stmt.executeUpdate(sql);// 
                if (result != -1) {
                    System.out.println("创建数据表成功");
                    sql = "insert into student(NO,name) values('2012001','陶伟基')";
                    result = stmt.executeUpdate(sql);
                    sql = "insert into student(NO,name) values('2012002','周小俊')";
                    result = stmt.executeUpdate(sql);
                    sql = "select * from student";
                    ResultSet rs = stmt.executeQuery(sql);
                    System.out.println("学号\t姓名");
                    while (rs.next()) {
                        System.out
                                .println(rs.getString(1) + "\t" + rs.getString(2));
                    }
                }
            } catch (SQLException e) {
                System.out.println("MySQL操作错误");
                e.printStackTrace();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                conn.close();
            }
        }
    }



    展开全文
  • java中的instance方法

    万次阅读 2017-02-24 23:09:07
    * 在主函数开始时调用,返回一个实例化对象,此对象是static的,在内存中保留着它的引用,即内存中有一块区域专门用来存放静态方法和变量, * 可以直接使用,调用多次返回同一个对象。 getInsta...

    更多文章查看个人主页www.liangyouze.com 

    关于对象的实例化   大家想到的通常是直接new,除了这个,还有些单实例模式,层次间调用等等

     

    getInstance的使用:
     * 在主函数开始时调用,返回一个实例化对象,此对象是static的,在内存中保留着它的引用,即内存中有一块区域专门用来存放静态方法和变量,
     * 可以直接使用,调用多次返回同一个对象。
    getInstance 和 new的区别;


    大部分类都可以用new,new就是通过生产一个新的实例对象,或者在栈上声明一个对象,每部分的调用
    *都是用的一个新的对象



    getInstance在单例模式(保证一个类仅有一个实例,并提供一个访问它的全局访问点)的类中常见,用来生成唯一的实例,getInstance往往是static的。

     

    public abstract class TestInstance { 
    
    static int i = 1; 
    
    public static TestInstance getInstance() { 
      
      System.out.println(i++); 
      return null; 
      
    } 
    } 
    
    public class TestGetInstance { 
    
    public static void main(String[] args) { 
      
      TestInstance ins1 = TestInstance.getInstance(); 
      TestInstance ins2 = TestInstance.getInstance(); 
    
    } 
    
    } 

     

     

     

     

     

     

    使用实例,在定义的新类当中加入getInstance()方法,返回值即为该类的一个对象,此方法常常应用在Java的单例模式当中

     

    public class OAuthConstant {  
      
        public static synchronized OAuthConstant getInstance(){  
            if(instance == null)  
                instance = new OAuthConstant();  
            return instance;  
        }  
    }

     

     

     

    //主函数当中使用此类的getInstance()函数,即可得到系统当前已经实例化的该类对象,若当前系统还没有实例化过这个类的对象,则调用此类的构造函数  
    //实例化一个对象,并返回  
    OAuthConstant.getInstance();  
    (1) 对象使用之前通过getInstance得到而不需要自己定义,用完之后不需要delete;
    (2)new 一定要生成一个新对象,分配内存;getInstance() 则不一定要再次创建,它可以把一个已存在的引用给你使用,这在效能上优于new;
    (3) new创建后只能当次使用,而getInstance()可以跨栈区域使用,或者远程跨区域使用。所以getInstance()通常是创建static静态实例方法的。
    (4)对于抽象类,是只能用getInstance()方法,是不能new出来的,
     
    总结:
    getInstance这个方法在单例模式用的甚多,为了避免对内存造成浪费,直到需要实例化该类的时候才将其实例化,所以用getInstance来获取该对象,
    至于其他时候,也就是为了简便而已,为了不让程序在实例化对象的时候,不用每次都用new关键字,索性提供一个instance方法,不必一执行这个类就
    初始化,这样做到不浪费系统资源!
    单例模式 可以防止 数据的冲突,节省内存空间

     

     

     

     

     

     

     

    展开全文
  • 通过反射获取对象 //1.获取Class对象 Class stuClass = ...Student xxxx=stuClass .newInstance(); 或者: //1.获取Class对象 Class stuClass = Class.forName(“fanshe.field.Student”); //获取一个对象...
  • 反射中newInstance方法

    千次阅读 2019-06-04 16:04:34
    反射中采用newInstance方法废弃,可采用getDeclaredConstructor().newInstance()方法来得到类对象
  • newInstance() 方法

    千次阅读 2021-07-26 17:04:56
    通过 Class 类的 newInstance() 方法创建对象,该方法要求该 Class 对应类有无参构造方法。执行 newInstance()方法实际上就是使用对应类的无参构造方法来创建该类的实例,其代码的作用等价于Super sup = new Super()...
  • 在Java9(包含)之后的版本中通过字节码直接调用getInstance()方法会报过时,如下: 解决方案 public static void main(String[] args) throws Exception { Class<?> clazz = Class.forName("java.lang....
  • 关于newInstance()方法有参数和无参数

    千次阅读 2021-05-31 16:39:47
    Class.newInstance() Constructor.newInstance() 二、两种创建方式的比较: Class.newInstance() 只能够调用无参的构造函数,即默认的构造函数; Constructor.newInstance() 可以根据传入的参数,调用任意构造函数。...
  • 反射中newinstance方法Deprecated的替代

    千次阅读 2019-01-16 10:10:07
    clazz.getDeclaredConstructor().newInstance()
  • Class类newInstance()方法newInstance()方法在java.lang包中可用。newInstance()方法用于创建此Class对象表示的类的新实例。newInstance()方法是一种非静态方法,只能通过类对象访问,如果尝试使用类名称访问该方法...
  • 记录:newInstance()过时的代替方法

    千次阅读 2019-10-08 17:05:56
    newInstance()过时的代替方法 getDeclaredConstructor().newInstance()
  • newInstance 方法不推荐使用

    千次阅读 2019-12-04 16:57:20
    报错: This inspection reports where deprecated code is used in the specified inspection scope。...class.getDeclaredConstructor().newInstance(); 全部代码: String beanPath = props.getProperty(b...
  • jdk9之后newInstance过时的替代方法

    千次阅读 2020-06-10 11:02:18
    查阅API之后可知 在jdk9之后class类中的newInstance()方法过时了 我们可以使用 personClass.getDeclaredConstructor().newInstance() 来代替newInstance
  • 相信大家在日常开发中,都有用到过Class.newInstance()方法,如果有人没有接触过,也没关系,我会给大家介绍下这个方法的使用方式。① 方法使用介绍:该方法属于静态方法,调用方式Class.newInstance(),返回的是...
  • 使用频率如此之高的Fragment,你的使用姿势,真的正确吗? 如果你还在new Fragment(), 不妨来看看谷歌默认推荐的Fragment.newInstance()吧
  • Java9之后显示已过时newInstance()方法

    万次阅读 2019-07-26 18:07:38
    反射案例 需求说明 定义一个类,在类中定义一个成员方法 show ,方法功能是:打印一个字符串。...clazz.getDeclaredConstructor().newInstance() 案例显示 package day25; public class Ca { public void show(...
  • instance_eval方法 这个BasicObject#instance_eval有点类似JS中的bind方法,不同的时,bind是将this传入到对象中,而instance_eval则是将代码块(上下文探针Context Probe)传入到指定的对象中,一个是传对象,一个是...
  • 2、newInstance() Class还有一个有用的方法可以为类创建一个实例,这个方法叫做newInstance()。例如: x.getClass.newInstance(),创建了一个同x一样类型的新实例。newInstance()方法调用默认构造器(无参数构造器...
  • Java类class newInstance()方法及示例

    千次阅读 2020-07-08 22:50:27
    类class newInstance()方法 (Class class newInstance() method) newInstance() method is available in java.lang package. newInstance()方法在java.lang包中可用。 newInstance() method is used to create a new...
  • Class类:public T newInstance() throws InstantiationException, IllegalAccessException 创建此 Class 对象所表示的类的一个新实例。如同用一个带有一个空参数列表的 new 表达式实例化该类。如果该类尚未初始化...
  • 被static修饰的方法为静态方法,之外的方法为实例方法。静态方法可直接使用类调用,实例方法必须创建实例后才能调用。 1. 示例 @Test void staticMethodTest(){ //直接调用静态方法 Boss.work(); //创建...
  • newInstance()方法已过时(即:@Deprecated(since = “9”)),快来康康怎办吖? The call clazz.newInstance() can be replaced by clazz.getDeclaredConstructor().newInstance() == 以上片段为jdk9的官方解释...
  • 在java1.9版本中,newInstance被弃用 ...getDeclaredConstructor()方法会根据他的参数对该类的构造函数进行搜索并返回对应的构造函数,没有参数就返回该类的无参构造函数,然后再通过newInstance进行
  • 报错:Exception in ... at java.lang.Class.newInstance(Class.java:427) at Test.main(Test.java:8) Caused by: java.lang.NoSuchMethodException: WanYue.<init>() at java.lang.Class.getConstructor0...
  • Java中instance的用法

    万次阅读 多人点赞 2018-09-05 15:13:04
    * 在主函数开始时调用,返回一个实例化对象,此对象是static的,在内存中保留着它的引用,即内存中有一块区域专门用来存放静态方法和变量, * 可以直接使用,调用多次返回同一个对象。 getInstance 和 new的区别...
  • 类名.getDeclaredConstructor().newInstance();

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 955,399
精华内容 382,159
关键字:

instance方法