java 反射获取对象的构造函数_通过反射获取对象的构造器

本文深入讲解Java中的构造器概念,包括构造器的作用、如何通过构造器初始化类成员属性,以及构造器重载等内容。此外,还介绍了如何使用反射API获取构造器并创建对象。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在学习这个之前,先复习下对象构造器的作用。

一、构造器:

构造方法的名字必须和所在类的名字一致,没有返回值,但不能声明void,访问权限可以为任意,但是一般情况下使用public方法权限,构造方法中的参数可以根据需要自行定义,参数的不同的构造方法构成重载;

例如:

public classPerson {privateString name;privateString age;//getter setter ..

public static voidmain(String[] args) {

Person person= newPerson();

}

}

这个Person对象,我们在通过new的时候,默认调用了对象的无参构造方法,通过无参构造方法对这个类进行初始化,当我们没有给出构造方法的时候,java会默认提供一个无参构造器。

当我给类一个构造器的时候,会默认覆盖类中的无参构造

public classPerson {privateString name;privateInteger age;

Person(String name,Integer age){this.age =age;this.name =name;

}//getter setter ..

public static voidmain(String[] args) {

Person person= new Person("张三",20);

}

}

在这个类中,我们就调用了我们创建的构造器去初始化对象

构造方法中的参数可以根据需要自行定义,参数的不同的构造方法构成重载

例:

public classFu {

Fu(){}//无参公有的构造方法

Fu(int i){} //参数为Int的公有构造方法

}

public class Zi extendsFu{Zi(){} //无参的公有构造方法

Zi(int i){} //参数类型为int的公有构造方法

Zi(int i,double d){} //参数类型为int和double的公有构造方法

}

java中构造方法的使用有两个地方,一个是跟在关键字new后面,类名加上一个小括号(),小括号内根据实际加上实参,

另外一个是跟在关键字super或this后加上一个小括号(),小括号内根据实际添加实参,下面进行举例。

调用本类的构造方法:

public class Zi extendsFu {

Zi() {this(2);//调用参数为int类型的本类的构造方法

}

}

调用父类的构造方法:

public class Zi extendsFu {

Zi() {super(2);//调用参数为int类型的父类的构造方法

}

}

注意:

public class Zi extendsFu {/*** 注意:例子中中this或super调用构造方法只能出现在构造方法中,

* 而且必须出现在第一行,所以一个构造方法中第一行只能为this或super

* 调用构造方法,两者不能同时调用构造方法出现,而且注意this或super

* 调用构造方法时,要留构造方法出口,意思就是最后调用的构造方法中没

* 有再调用别的构造方法!(下面并不能一起参数相同的构造器,演示需求)*/Zi() {this(2);//调用参数为int类型的本类的构造方法

}

Zi() {super(2);//调用参数为int类型的父类的构造方法

}

}

构造方法的作用

为了初始化成员属性,而不是初始化对象,初始化对象是通过new关键字实现的

通过new调用构造方法初始化对象,编译时根据参数签名来检查构造函数,称为静态联编和编译多态(参数签名:参数的类型,参数个数和参数顺序)

创建子类对象会调用父类构造方法但不会创建父类对象,只是调用父类构造方法初始化父类成员属性

我总是要把构造器和方法混淆,后来发现,方法实际上是需要用于执行java代码的,而构造器,构造器是一个类的实例!

为什么呢?

类的实例,我们需要用类来创建对象,进而访问其属性,因为实例是需要被用来调用的,但是调用的话,我们不得不去考虑一个问题,就是对象,最终是被存储在内存里面的,而存储的时候,

我们的内存不得不需要给他再另外开辟新的内存空间,那么,java是如何给这种我们所需要的类来开辟内存空间的呢?这就涉及到了java的内存机制,就是说,我们必须要给这个类制作一个构造器,

而且这个构造器的名称必须和这个类的名称是一致的,这样,我们的java编译器才能识别这个类,进而给这个类在内存中开辟内存空间,也就是我们所说的,我们手动,人为的给他进行“初始化”,事例如下:

public classFu {

Fu(){

System.out.println("Construct");

}//无参公有的构造方法

Fu(int i){} //参数为Int的公有构造方法

}

这样,当我们在对Fu类进行调用的时候,我们的java编译器就会事先对他进行“自动”地初始化,开辟内存空间

那么现在问题又来了,举个例子,我们的Fu()方法需要带有一个参数,形参,但是整个代码中,需要不仅仅是带有形参的Fu();还需要不带形参的Fu(),在我们的构造器对类进行构造的时候,

需要将功能类似的,但形参不同的方法同时打包在该类下,以便在我们调用某个方法的时候,直接重载构造器中的该方法,可以说,这种构造形式,满足了我们对功能类似,形参不同的方法,

调用的时候,进行重载,而满足了编译器自动初始化,人不需要手动初始化的需求。

而且有个,问题,本来两个方法,功能上是类似的,一棵树和一株树苗,你非得要给他们起不同的名字,多别扭,好在有了构造器,能够是功能相似的方法起相同的名字,

不同的参数,而能够在被调用的时候得以重载,多么牛逼的构造器啊。

二、通过反射获取公共的构造器,并使用构造器创建对象

创建对象:

public classAnimal {privateString name;privateString sex;privateInteger age;//无参构造器

Animal(){}//有参构造

Animal(String name, String sex, Integer age) {this.name =name;this.sex =sex;this.age =age;

}

}

/*** 通过获取类的构造器来实例化对象*/

public static void main(String[] args) throwsException {

Class> animal = Class.forName("constructure.Animal");

Constructor[] constructors=animal.getDeclaredConstructors();/*** 输出:

* constructure.Animal 0

* ----------------

* constructure.Animal 3

* class java.lang.String

* class java.lang.String

* class java.lang.Integer

* ----------------*/

for (Constructor>constructor : constructors){//获取类中的构造器名称与构造器个数

System.out.println(constructor.getName()+" "+constructor.getParameterCount());//获取构造器的参数类型

Class>[] paramType =constructor.getParameterTypes();for (Class>param : paramType){

System.out.println(param);

}

System.out.println("----------------");

}//通过反射取得构造器并实例化对象//参数个数代表想要获取的那个构造器

Constructor> constructor =animal.getDeclaredConstructor();//调用了无构造器!//Animal{name='null', sex='null', age=null}

Object animalInstance =constructor.newInstance();

System.out.println(animalInstance);//调用有参构造实例化对象,先获取有参构造器

Constructor> constructor1 = animal.getDeclaredConstructor(String.class,String.class,Integer.class);//Animal{name='小猪', sex='公', age=10}

Object object = constructor1.newInstance("小猪","公",10);

System.out.println(object);

}

想获取什么构造器就根据需要的参数类型传入getDeclaredConstructor

注意:getDeclaredConstructor 与getConstructor的区别

getDeclaredConstructor 代表获取该class对象下所有的构造器,而getConstructor只能获取被public声明的构造器,有时候idea会提示多余代码,代码洁癖可能就将public去掉了,这样使用getConstructor就无法获取Construct

例如:

//无参构造器

publicAnimal(){

System.out.println("调用了无构造器!");

}

Animal(){

System.out.println("调用了无构造器!");

}

这两个无参构造器,没有被public修饰的就无法通过getConstructor方法获取他的构造器

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值