1.最近在看反射的东西,通过Class对象的构造方法,去创建对象
java对象
package com.newland.draw.reflect;
public class Person {
public Person() {
System.out.println("无参");
}
public Person(String name) {
System.out.println(name);
this.name = name;
}
public Person(int age) {
System.out.println(age);
this.age = age;
}
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
通过反射去创建java对象
package com.newland.draw.reflect;
import java.lang.reflect.Constructor;
public class Client {
public static void main(String[] args) throws Exception{
/**
* 获取Person 接口的Class对象三种方式
* //
* 前提1.已知具体的类 2.已知类的全路径3.已知某个类的实例4.
* 1.Class.forName(xxx)
* 2.xxx.class
* 3.xxx.getClass()
* 4.通过类加载器获取loadClass(xxx)
注意,这并不是我们new了一个Class对象,而是让虚拟机加载并创建Class对象
**/
Class personClazz = Person.class;
//获取有参的构造函数
Constructor constr = personClazz.getConstructor(String.class);
//通过有参的构造函数创建对象
Person person = (Person) constr.newInstance("张三");
System.out.println(person);
运行结果:
张三
com.newland.draw.reflect.Person@15db9742
上述代码 可以看到,通过反射成功创建对象,我发现一个问题,如果我有两个String类型的字段的构造函数,那么我是通过哪个构造函数创建的对象呢?于是我就尝试一下,下面可以看到,看来我的担心是多余的,直接报错了。看来代码写多了,很多细节性的东西都忘了。原来 构造函数是不允许参数结构相同的。看来有必要巩固一下基础知识了。
构造函数知识点1:
定义:构造函数是一种特殊的函数。其主要功能是用来在创建对象时初始化对象, 即为对象成员变量赋初始值,总与new运算符一起使用在创建对象的语句中。构造函数与类名相同,可重载多个不同的构造函数。
构造函数知识点2:
1.构造器的名称必须与类名同名,包括大小写。
2.构造器没有返回值,但也不能写void,也不能写return。
3.构造器的参数:一般是初始化对象的前提条件。
4.用new调用!且对象一建立,构造器就运行且仅运行一次。一般方法可被调用多次。
5.类一定有构造器!这是真的,不需要质疑!接口没有构造器,因为接口不能被实例化。
6.如果类没有声明(定义)任何的构造器,Java编译器会自动插入默认构造器!
7.默认构造是无参数,方法体是空的构造器,且默认构造器的访问权限随着所属类的访问权限变化而变化。如,若类被public修饰,则默认构造器也带public修饰符。
8.默认构造器是看不到的,一旦自己写上构造器则默认构造器就没有了,自己写的叫自定义构造器,即便自己写的是空参数的构造器,也是自定义构造器,而不是默认构造器。
9.如果类声明了构造器,Java编译器将不再提供默认构造器。若没手动写出无参构造器,但却调用了无参构造器,将会报错!
验证:9,写了一个有参的构造函数,通过无参构造函数去实例化对象
结果:通过new 关键字直接报错,通过反射找不到该方法,验证正确
10.构造器是可以重载的,重载的目的是为了使用方便,重载规则与方法重载规则相同。
11.构造器是不能继承的!虽说是叫构造方法,但实际上它不是常说的一般方法。
12.子类继承父类,那么子类型构造器默认调用父类型的无参数构造器。
13.子类构造器一定要调用父类构造器,如果父类没有无参数构造器,则必须使用super(有参数的),来调用父类有参的构造器。 那么,为什么子类一定要访问父类的构造器?因为父类中的数据子类可以直接获取。所以子类对象在建立时,需要先查看父类是如何对这些数据进行初始化的,所以子类在对象初始化时,要先访问一下父类中的构造器。总之,子类中至少会有一个构造器会访问父类中的构造器,且子类中每一个构造函数内的第一行都有一句隐式super()。
验证12,13 我们将Person类作为父类
package com.newland.draw.reflect;
public class Person {
public Person(String name) {
System.out.println(name);
this.name = name;
}
private String name;
private String address;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
新建Young类作为子类,继承Person类,可以看到,子类上出现红色下划线,提示我们需要添加构造方法。
添加上去
public class Young extends Person{
public Young(String name) {
super(name);
// TODO Auto-generated constructor stub
}
}
测试:
子类不能通过无参构造函数创建对象,如果想通过无参构造函数改怎么办?可以看到,还是需要在子类的构造函数里调用super(name)方法。
当我们给父类加上无参的构造方法时,子类也可以通过无参的构造方法进行实例化,12,13正确。
14.注意事项:sper()、sper.和 this()、this.
15.this:在运行期间,哪个对象在调用this所在的方法,this就代表哪个对象,隐含绑定到当前“这个对象”。
16.super():调用父类无参构造器,一定在子类构造器第一行使用!如果没有则是默认存在super()的!这是Java默认添加的super()。
17.super.是访问父类对象,父类对象的引用,与this.用法一致
18.this():调用本类的其他构造器,按照参数调用构造器,必须在构造器中使用,必须在第一行使用,this() 与 super() 互斥,不能同时存在
19.this.是访问当前对象,本类对象的引用,在能区别实例变量和局部变量时,this可省略,否则一定不能省!
如果子父类中出现非私有的同名成员变量时,子类要访问本类中的变量用this. ;子类要访问父类中的同名变量用super.