【JavaSE|Java的反射技术(Class类,Constructor类,Method类, Field类)】Java编码时知道类和对象的具体信息,此时直接对类和对象进行操作即可,无需反射 如果编码时不知道类或者对象的具体信息,此时应该使用反射来实现为什么要使用反射
- 反射就是把Java类中的各种成分映射成一个个的java对象。例如,一个类有:成员变量,方法,构造方法,包等等信息,利用反射技术可以对一个类进行解剖,把各个组成部分映射成一个个对象。
比如类的名称放在XML文件中,属性和属性值放在XML文件中,需要在运行时读取XML文件,动态获取类的信息。
在编译时根本无法知道该对象或类可能属于哪些类,程序只依靠运行时信息来发现该对象和类的真实信息。
反射的作用:创建对象、操作属性、调用方法
如何使用反射 掌握反射技术的要点在于:如何从一个class中反射出各个组成部分。反射出来的对象怎么用。
Class类 Class类:代表一个类,是Java反射机制的起源和入口,用于获取与类相关的各种信息
提供了获取类信息的相关方法(Class类继承自Object类)
Class类是所有类的共同的图纸
每个类有自己的对象,同时每个类也看做是一个对象,有共同的图纸Class,存放类的结构信息,能够通过相应方法取出相应的信息:类的名字、属性、方法、构造方法、父类和接口。
总之,只要是在源程序中出现的类型,都有各自的Class实例对象,例如,int,void…
反射就是把Java类中的各种成分映射成一个个的java对象。例如,一个类有:成员变量,方法,构造方法,包等等信息,利用反射技术可以对一个类进行解剖,把各个组成部分映射成一个个对象。
那么,既然反射的作用是创建对象、操作属性、调用方法,要实现以上3个作用,需要用到下面介绍的3个类:Constructor类,Method类, Field类
Constructor类 (1)Constructor类代表某个类中的一个构造方法
得到某个类所有的构造方法:
例子:
Constructor [] constructors= Class.forName("java.lang.String").getConstructors();
得到某一个构造方法:
例子: //获得方法时要用到类型
Constructor constructor = Class.forName(“java.lang.String”).getConstructor(StringBuffer.class);
(2)创建实例对象:
通常方式:
String str = new String(new StringBuffer("abc"));
反射方式:
String str = (String)constructor.newInstance(new StringBuffer("abc"));
Class.newInstance()方法:
例子:
String obj = (String)Class.forName("java.lang.String").newInstance();
该方法内部先得到默认的构造方法,然后用该构造方法创建实例对象。
Method类 Method类代表某个类中的一个成员方法
得到类中的某一个方法——
例子:
Method charAt = Class.forName("java.lang.String").getMethod("charAt", int.class);
调用方法——
通常方式:
System.out.println(str.charAt(1));
反射方式:
System.out.println(charAt.invoke(str, 1));
如果传递给Method对象的invoke()方法的第一个参数为null,这有着什么样的意义呢?说明该Method对象对应的是一个静态方法!
jdk1.4和jdk1.5的invoke方法的区别:
Jdk1.5:public Object invoke(Object obj,Object… args)
Jdk1.4:public Object invoke(Object obj,Object[] args),即按jdk1.4的语法,需要将一个数组作为参数传递给invoke方法时,数组中的每个元素分别对应被调用方法中的一个参数,所以,调用charAt方法的代码也可以用Jdk1.4改写为 charAt.invoke(“str”, new Object[]{1})形式。
Field类 Field类代表某个类中的一个成员变量
问题:得到的Field对象是对应到类上面的成员变量,还是对应到对象上的成员变量?类只有一个,而该类的实例对象有多个,如果是与对象关联,哪关联的是哪个对象呢?所以字段fieldX 代表的是x的定义,而不是具体的x变量。(注意访问权限的问题)
示例代码:
ReflectPoint point = new ReflectPoint(1,7);
Field y = Class.forName("cn.itcast.corejava.ReflectPoint").getField("y");
System.out.println(y.get(point));
//Field x = Class.forName("cn.itcast.corejava.ReflectPoint").getField("x");
Field x = Class.forName("cn.itcast.corejava.ReflectPoint").getDeclaredField("x");
x.setAccessible(true);
System.out.println(x.get(point));
实例演示 首先,我们自定义一个Person类,它是我们将要进行反射的目标。.
在这个类里面,我们定义了:
1.构造方法
2.实例方法
3.属性
package cn.itcast.reflect;
import java.io.InputStream;
import java.util.List;
public class Person { public String name = "yaoer";
private int password = 123;
private static int age = 23;
public Person() {
System.out.println("person");
} public Person(String name) {
System.out.println(name);
} public Person(String name, int password) {
System.out.println(name + ":" + password);
} private Person(List list) {
System.out.println("list");
} public void aa1() {
System.out.println("aaa1");
} public void aa1(String name, int password) {
System.out.println(name + ":" + password);
} public String aa1(String name, int[] password) {
return new String("adad");
} private void aa1(InputStream in) {
System.out.println(in);
} public static void aa1(int num) {
System.out.println(num);
} public static void main(String[] args) {
System.out.println("main!");
}
}
反射:类的构造函数 ,创建类的对象
package cn.itcast.reflect;
import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.List;
import org.junit.Test;
//解剖(反射)类的构造函数 ,创建类的对象
public class Demo2 { // 1——反射构造函数:public Person()
@Test
public void test1() throws Exception {Class> clazz = Class.forName("cn.itcast.reflect.Person");
Constructor> c = clazz.getConstructor(null);
Person p = (Person) c.newInstance(null);
System.out.println(p.name);
} // 2——反射构造函数:public Person(String name)
@Test
public void test2() throws Exception {Class> clazz = Class.forName("cn.itcast.reflect.Person");
Constructor> c = clazz.getConstructor(String.class);
Person p = (Person) c.newInstance("xxxooo");
System.out.println(p.name);
} // 3——反射构造函数:public Person(String name,int password)
@Test
public void test3() throws Exception {Class> clazz = Class.forName("cn.itcast.reflect.Person");
Constructor> c = clazz.getConstructor(String.class,int.class);
Person p = (Person) c.newInstance("xxxooo",20);
System.out.println(p.name);
}
// 4——反射构造函数:private Person(List list)
@Test
public void test4() throws Exception {Class> clazz = Class.forName("cn.itcast.reflect.Person");
Constructor> c = clazz.getDeclaredConstructor(List.class);
c.setAccessible(true);
//暴力反射
Person p = (Person) c.newInstance(new ArrayList());
System.out.println(p.name);
}@Test
public void test5() throws Exception {Class> clazz = Class.forName("cn.itcast.reflect.Person");
Person p = (Person) clazz.newInstance();
}
}
反射:类中的方法
/**
*
*/
package cn.itcast.reflect;
import java.io.FileInputStream;
import java.io.InputStream;
import java.lang.reflect.Method;
import org.junit.Test;
/**
* 反射类中的方法
*
*/
public class Demo3 {
// 反射类的方法: public void aa1(){
@Test
public void test1() throws Exception {Class clazz = Class.forName("cn.itcast.reflect.Person");
Method method = clazz.getMethod("aa1", null);
Object obj = clazz.newInstance();
method.invoke(obj, null);
} // 反射类的方法: public void aa1(String name,int password){
@Test
public void test2() throws Exception {Class clazz = Class.forName("cn.itcast.reflect.Person");
Method method = clazz.getMethod("aa1", String.class, int.class);
Object obj = clazz.newInstance();
method.invoke(obj, "yaoer", 24);
} // 反射类的方法: public void aa1(String name,int[] password){
@Test
public void test3() throws Exception {Class clazz = Class.forName("cn.itcast.reflect.Person");
Method method = clazz.getMethod("aa1", String.class, int[].class);
int[] a = new int[] { 1, 2, 3 };
Object obj = clazz.newInstance();
System.out.println(method.invoke(obj, "yaoer", a));
} // 反射类的方法:private void aa1(InputStream in)
@Test
public void test4() throws Exception {Class clazz = Class.forName("cn.itcast.reflect.Person");
Method method = clazz.getDeclaredMethod("aa1", InputStream.class);
// private
method.setAccessible(true);
Object obj = clazz.newInstance();
System.out.println(method.invoke(obj, new FileInputStream("c://1.txt")));
// 对应目录下需要存在此文件
} // 反射类的方法:public static void aa1(int num) {
@Test
public void test5() throws Exception {Class clazz = Class.forName("cn.itcast.reflect.Person");
Object obj = clazz.newInstance();
Method m = clazz.getMethod("aa1", int.class);
m.invoke(obj, 23);
} // 反射类的方法: public static void main(){
@Test
public void test6() throws Exception {Class clazz = Class.forName("cn.itcast.reflect.Person");
Method method = clazz.getMethod("main", String[].class);
// method.invoke(null, new Object[] {new String[] {"aa","bb"}});
method.invoke(null, (Object) new String[] { "aa", "bb" });
}}
反射:类中的字段(属性)
/**
*
*/
package cn.itcast.reflect;
import java.lang.reflect.Field;
import org.junit.Test;
/**
* 反射字段
*
*/
public class Demo5 { // 反射字段:public String name = "yaoer";
@Test
public void test1() throws Exception {
Class clazz = Class.forName("cn.itcast.reflect.Person");
Object obj = clazz.newInstance();
Field f = clazz.getField("name");
// 获取字段的值
Object val = f.get(obj);
// 获取字段的类型
Class type = f.getType();
if (type.equals(String.class)) {
String sval = (String) val;
System.out.println(sval);
}// 设置字段的值
f.set(obj, "zhuzhu");
System.out.println(f.get(obj));
} // 反射字段:private int password;
;
@Test
public void test2() throws Exception {
Class clazz = Class.forName("cn.itcast.reflect.Person");
Object obj = clazz.newInstance();
Field f = clazz.getDeclaredField("password");
f.setAccessible(true);
// 改变访问权限System.out.println(f.get(obj));
} // 反射字段:private static int age = 23;
@Test
public void test3() throws Exception {
Class clazz = Class.forName("cn.itcast.reflect.Person");
Object obj = clazz.newInstance();
Field f = clazz.getDeclaredField("age");
f.setAccessible(true);
// 改变访问权限System.out.println(f.get(obj));
}}
反射技术优缺点
- 优点
反射是其他一些常用语言,如C、C++、Fortran或者Pascal等不具备的
Java反射技术应用领域很广,如软件测试、JavaBean等
许多流行的开源框架例如Struts、Hibernate、Spring在实现过程中都采用了该技术
- 缺点
使用反射会模糊程序内部逻辑:程序员希望在代码中看到程序的逻辑,反射等绕过了源代码的技术,因而会带来维护问题。反射代码比相应的直接代码更复杂
参考文章:https://blog.csdn.net/Elias94/article/details/80361035
推荐阅读
- Java学习|Java>获取Class对象的三种方式,及其Method、Field、Constructor对象的使用方法
- java|学习Java期末总结
- 基础Java练习15(打印水仙花数)
- 基础Java练习19(测试从出生到现在活了多久)
- java|基础Java练习20(词频统计)
- 时区|springboot new Date() 时区差8小时
- 用Java十多年了,能“精通Java”了吗()
- JavaWeb|JSP-02动态网页技术基础
- java|Java-Mybatis(四): 动态SQL、标签、缓存