java基础-反射3(反射,反射创建对象,操作对象属性,调用对象方法)
前面通过学习,我们了解的运行时类型信息的基本原理,以及通过Class对象和反射来获取运行时类型信息。下面来了解通过反射来创建对象,以及操作对象的属性和方法
首先还是创建一个person类
@Service
public class Person1 extends PersronParent implements PersonInterfance ,Cloneable{
public String name;
public double weight;
protected double height;
private Integer age;
public Person1(){}
protected Person1(String name){
}
public void publicShow() throws Exception{
System.out.println("publicShow()");
}
protected void disPlay(){
System.out.println("disPlay()");
}
private String privateShow(String paramter1,String paramter2) throws NullPointerException{
StringBuffer stringBuffer = new StringBuffer(paramter1);
return stringBuffer.append(paramter2).toString();
}
@Deprecated
private int testParamter(String paramter1,String paramter2) throws NullPointerException{
return 1;
}
@Deprecated
public int testPublicParamter(String paramter1,String paramter2) throws NullPointerException{
return 1;
}
@Override
public void parentSay(){
super.parentSay();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getWeight() {
return weight;
}
public void setWeight(double weight) {
this.weight = weight;
}
public double getHeight() {
return height;
}
public void setHeight(double height) {
this.height = height;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", weight=" + weight +
", height=" + height +
", age=" + age +
'}';
}
通过反射来创建对象
通常在java中我们有以下4中方式创建对象
- 通过new 关键字 创建对象
- 通过Object clone();方法
- 通过反序列化
- 通过反射创建
这里我们来了解通过反射来创建对象和调用方法
首先我们来看通过反射来创建对象
我们通过newInstance()来创建对象,如果对于无参数的构造方法我们直接用Class的对象的newInstance()就可以创建对象
如果对于有参数的构造方法,我们需要先获取带参数的构造器(注意权限修饰符),然后通过构造器的newInstance()方法创建对象。
public class TestReflect {
public static void main(String[] agrs){
Class<Person> personClass = Person.class;
try {
/**
* 通过无参数的构造方法创建对象
*/
Person personOne = personClass.newInstance();
/**
* 通过有参数的构造方法创建对象
*/
Constructor constructor = personClass.getDeclaredConstructor(String.class);
Person personTwo = (Person) constructor.newInstance("带参数");
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
运行结果如下
这样我们就可以通过反射来创建对象。
通过反射创建对象后可以通过反射来给操作对象的属性
通过反射操作对象属性
上一篇文章说过,类的属性在反射中使用java.lang.reflect.Field表示,当然也使用这个类来操作对象的属性,在java中属性的访问涉及到权限修饰的修饰,具体如下:
所以在操作对象的属性的需要注意对目标类属性访问的权限,如下
如果当前类对目标对象有访问的权限(如目标类属性为public)
- 通过Class对象的getField()获取Field。
- 然后通过Field的set()方法对目标对象赋值。
如果当前类对目标对象没有访问的权限(如目标类属性为private)
- 通过Class对象的getDeclaredField()获取Field。
- 调用Field 的setAccessible(true)方法,设置为可访问(如果不设置为true,则在当前类中不能访问目标类的属性,在为目标对象赋值时会报错)
- 然后通过Field的set()方法对目标对象赋值。
- 调用Field 的setAccessible(false)方法复原。
具体操作如下
public class TestFileId2 {
public static void main(String agrs[]) throws NoSuchFieldException {
try {
//获取Class 对象
Class<Person> personClass = Person.class;
//创建目标对象(注意,我们这里直接用的object,更体现了运行时类型信息)
Object person = personClass.newInstance();
//在没有通过反射赋值之前
System.out.println("person对象在没有赋值之前");
System.out.println(person.toString());
System.out.println();
System.out.println("当前类可以操作目标类的属性:比如public权限的属性");
//获取有权限操作的属性(当前类可以操作目标对象的属性:比如public)
Field name = personClass.getField("name");
//为person 对象 的 name属性赋值为 TestName
name.set(person,"TestName");
System.out.println(person.toString());
System.out.println();
System.out.println("当前类不能够操作目标类的属性:比如private权限的属性");
Field age = personClass.getDeclaredField("age");
//为person 对象 的 age 属性设置为可访问
age.setAccessible(true);
//为person 对象 的 age属性赋值为 10
age.set(person,10);
age.setAccessible(false);
System.out.println(person.toString());
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
运行结果如下
通过反射调用对象方法
反射能够操作对象的属性,当然也可以操作对象的方法,方法通过java.lang.reflect.Method表示,由于访问权限的限制,对于方法也有如下操作
如果当前类对目标对象有访问的权限(如目标类方法为public)
- 通过Class对象的getMethod()获取Method。
- 然后通过Method的invoke()方法对目标对象赋值。
如果当前类对目标对象没有访问的权限(如目标类方法为private)
- 通过Class对象的getDeclaredMethod()获取Method。
- 调用Method的setAccessible(true)方法,设置为可访问(如果不设置为true,则在当前类中不能访问目标类的方法,在调用目标类的方法时会报错)
- 然后通过Method的invoke()方法对目标对象赋值。
- 调用Method的setAccessible(false)方法复原。
具体操作如下:
public class TestMethod2 {
public static void main(String agrs[]) throws NoSuchFieldException, NoSuchMethodException, InvocationTargetException {
try {
//获取Class 对象
Class<Person> personClass = Person.class;
//创建目标对象
Object person = null;
person = personClass.newInstance();
System.out.println("当前类可以操作目标类的方法:比如public权限的方法");
//获取有权限操作的方法(当前类可以操作目标对象的方法:比如public)
Method publicShow = personClass.getMethod("publicShow");
//通过Method 的invoke 调用person 的 publicShow方法
publicShow.invoke(person);
System.out.println("当前类不能够操作目标类的方法:比如private权限的方法");
Method privateShow = personClass.getDeclaredMethod("privateShow", String.class, String.class);
//为person 对象 的 privateShow 方法设置为可访问
privateShow.setAccessible(true);
//通过Method 的invoke 调用person 的 privateShow方法
String result = (String) privateShow.invoke(person, "参数1", "参数2");
System.out.println(result);
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
运行结果如下:
以上就是通过反射操作对象的基本方式。
反射的基础知识就是以上几篇文章,反射相对于其他知识来说比较简单,但是反射应用很多,比如很多框架,以及java中的动态代理等都涉及到了,所以反射在java中还是很重要的。