目录
一、概念
二、类类
1、类类的获取方式
1)类名.Class
2)对象.getClass()
3)Class.forName()
三、反射实例化
1、调用一个公有的无参构造方法
2、调用一个公有的一个参构造方法
3、调用一个公有的两个参构造方法
4、调用一个私有的一个参构造方法
四、反射:方法调用
1、公有无参
2、公有有参
3、私有有参
完整代码:
五、反射:读写属性
一、概念
J2EE中的反射(Reflection)是指在程序运行期间访问、检测和修改自身的状态或行为。通过反射,可以动态地获取一个类的所有成员变量、方法、构造函数等信息,并且可以在运行时调用这些成员。在J2EE中,反射可以方便地实现一些框架、ORM工具,以及其他动态性能要求的应用程序。
什么是反射?
反射(Reflection)是一种在运行时动态地获取和操作对象的能力,它允许程序通过对象的类类型来了解对象的成员和方法,并且可以在运行时调用这些成员和方法。反射可以用于许多目的,例如在运行时动态加载类、实例化对象、查看和修改对象的属性和方法、调用私有方法和构造函数,等等。在Java中,反射通过java.lang.reflect包中的类和接口来实现。反射的优点是可以使我们的代码更加灵活和动态,但是反射的开销比较大,因此在性能要求较高的情况下,应该谨慎使用。
总的来说:反射Java语言中的一种机制,通过这种机制可以动态的实例化对象、读写属性、调用方法
二、类类
在Java反射(reflection)中,Class类被称为“类类”(class of class),因为它代表了JVM中的一个类。每个Java类在内存中都有一个对应的Class类实例对象,可以通过Java的反射机制获取。通过这个实例,我们可以动态地获取、创建、操作一个类的各种元数据(如属性、方法、注解等),并可以在程序运行时动态地创建、修改该类的对象。通过反射,我们可以实现更加灵活和动态的编程方式,可以在编码阶段不确定访问的类和方法,直到运行时才确定需要获取和调用的类和方法。
1、类类的获取方式
1. Object类中的getClass()方法:可以获取一个对象所属的类。
2. 类名.class:直接通过类名这种语法形式获取一个类的Class实例对象。
3. Class.forName(String className):通过类的全限定名获取Class实例对象,需要处理ClassNotFoundException异常。
这些方式均可以获得一个Java类的Class实例对象,从而可以利用反射机制获取该类的一系列信息,如属性、方法、构造方法、注解等。
1)类名.Class
在开始示例的前期准备工作我们写一个类(Class)
package com.tgq.reflect;
/**
* 一个类
*
* @author tgq
*
*/
public class Student {
private String sid;
private String sname;
public Integer age;
static {
System.out.println("加载进jvm中!");
}
public Student() {
super();
System.out.println("调用无参构造方法创建了一个学生对象");
}
public Student(String sid) {
super();
this.sid = sid;
System.out.println("调用带一个参数的构造方法创建了一个学生对象");
}
public Student(String sid, String sname) {
super();
this.sid = sid;
this.sname = sname;
System.out.println("调用带二个参数的构造方法创建了一个学生对象");
}
@SuppressWarnings("unused")
private Student(Integer age) {
System.out.println("调用Student类私有的构造方法创建一个学生对象");
this.age = age;
}
public String getSid() {
return sid;
}
public void setSid(String sid) {
this.sid = sid;
}
public String getSname() {
return sname;
}
public void setSname(String sname) {
this.sname = sname;
}
public void hello() {
System.out.println("你好!我是" + this.sname);
}
public void hello(String name) {
System.out.println(name + "你好!我是" + this.sname);
}
@SuppressWarnings("unused")
private Integer add(Integer a, Integer b) {
return new Integer(a.intValue() + b.intValue());
}
}
编写好一个类之后我们开始调用方法进行拿去:代码示例
package com.tgq.reflect;
/**
* 类类的获取方式: 1、类名.Class 2、对象.getClass(); 3、Class.forName();
*
* @author tgq
*
*/
public class Demo_01 {
@SuppressWarnings("rawtypes")
public static void main(String[] args) throws Exception {
// 1、类名.Class
Class c1 = Student.class;
System.out.println(c1);
}
}
输出结果:
2)对象.getClass()
package com.tgq.reflect;
/**
* 类类的获取方式: 1、类名.Class 2、对象.getClass(); 3、Class.forName();
*
* @author tgq
*
*/
public class Demo_01 {
@SuppressWarnings("rawtypes")
public static void main(String[] args) throws Exception {
// 1、类名.Class
// Class c1 = Student.class;
// System.out.println(c1);
// 2、对象.getClass();
Student student = new Student();
Class c2 = student.getClass();
System.out.println(c2);
}
}
输出结果:
3)Class.forName()
package com.tgq.reflect;
/**
* 类类的获取方式: 1、类名.Class 2、对象.getClass(); 3、Class.forName();
*
* @author tgq
*
*/
public class Demo_01 {
@SuppressWarnings("rawtypes")
public static void main(String[] args) throws Exception {
// 1、类名.Class
// Class c1 = Student.class;
// System.out.println(c1);
// 2、对象.getClass();
// Student student = new Student();
// Class c2 = student.getClass();
// System.out.println(c2);
// 3、Class.forName();
Class c3 = Class.forName("com.tgq.reflect.Student");
System.out.println(c3);
}
}
输出结果:
三、反射实例化
在Java中,可以使用反射来实例化一个类。具体实现可以通过Class类的newInstance()方法或者Constructor类的newInstance()方法来实现。
三个常用的方法:getConstructor (),getDeclaredConstructor () ,newInstance() 。
一切的反射从类类开始
1、调用一个公有的无参构造方法
public class Demo_02 {
@SuppressWarnings("rawtypes")
public static void main(String[] args) throws Exception {
// 一切反射从类类开始
// 不管是哪一种获取类类的方法都是可以的
// Class c1 = Class.forName("com.tgq.reflect.Student");
// Student student = new Student();
// Class c1 = student.getClass();
Class c1 = Student.class;
/*
* 1、调用一个无参构造器反射实例化: 如果没有无参构造器是会报错的
*/
Student stu1 = (Student) c1.newInstance();
System.out.println(stu1);
}
}
输出结果:
2、调用一个公有的一个参构造方法
public class Demo_02 {
@SuppressWarnings("rawtypes")
public static void main(String[] args) throws Exception {
// 一切反射从类类开始
// 不管是哪一种获取类类的方法都是可以的
// Class c1 = Class.forName("com.tgq.reflect.Student");
// Student student = new Student();
// Class c1 = student.getClass();
Class c1 = Student.class;
/*
* 1、调用一个无参构造器反射实例化: 如果没有无参构造器是会报错的
*/
Student stu1 = (Student) c1.newInstance();
System.out.println(stu1);
/*
* 调用有参构造器必须要实例化构造器对象 2、调用一个有一个参数的构造器:getConstructor == 获取构造器对象
*
* parameterTypes:代表了参数的类别Class
*/
Constructor con1 = c1.getConstructor(String.class);
Student stu2 = (Student) con1.newInstance("s1");
System.out.println(stu2);
}
}
输出结果:
3、调用一个公有的两个参构造方法
public class Demo_02 {
@SuppressWarnings("rawtypes")
public static void main(String[] args) throws Exception {
// 一切反射从类类开始
// 不管是哪一种获取类类的方法都是可以的
// Class c1 = Class.forName("com.tgq.reflect.Student");
// Student student = new Student();
// Class c1 = student.getClass();
Class c1 = Student.class;
/*
* 1、调用一个无参构造器反射实例化: 如果没有无参构造器是会报错的
*/
Student stu1 = (Student) c1.newInstance();
System.out.println(stu1);
/*
* 调用有参构造器必须要实例化构造器对象 2、调用一个有一个参数的构造器:getConstructor == 获取构造器对象
*
* parameterTypes:代表了参数的类别Class
*/
Constructor con1 = c1.getConstructor(String.class);
Student stu2 = (Student) con1.newInstance("s1");
System.out.println(stu2);
/*
* 3、调用两个参数的构造器实例化
*/
Constructor con2 = c1.getConstructor(String.class, String.class);
Student stu3 = (Student) con2.newInstance("s1", "sb");
System.out.println(stu3);
}
}
输出结果:
4、调用一个私有的一个参构造方法
public class Demo_02 {
@SuppressWarnings("rawtypes")
public static void main(String[] args) throws Exception {
// 一切反射从类类开始
// 不管是哪一种获取类类的方法都是可以的
// Class c1 = Class.forName("com.tgq.reflect.Student");
// Student student = new Student();
// Class c1 = student.getClass();
Class c1 = Student.class;
/*
* 1、调用一个无参构造器反射实例化: 如果没有无参构造器是会报错的
*/
Student stu1 = (Student) c1.newInstance();
System.out.println(stu1);
/*
* 调用有参构造器必须要实例化构造器对象 2、调用一个有一个参数的构造器:getConstructor == 获取构造器对象
*
* parameterTypes:代表了参数的类别Class
*/
Constructor con1 = c1.getConstructor(String.class);
Student stu2 = (Student) con1.newInstance("s1");
System.out.println(stu2);
/*
* 3、调用两个参数的构造器实例化
*/
Constructor con2 = c1.getConstructor(String.class, String.class);
Student stu3 = (Student) con2.newInstance("s1", "sb");
System.out.println(stu3);
/*
* 4、调用一个私有的带一个参数的构造器实例化: getConstructor只能获取公有的构造器对象
*
* getDeclaredConstructor:获取私有的构造器对象
*/
Constructor con3 = c1.getDeclaredConstructor(Integer.class);
// 打开私有的访问权限
con3.setAccessible(true);
Student stu4 = (Student) con3.newInstance(1);
System.out.println(stu4);
}
}
输出结果:
四、反射:方法调用
1、公有无参
public class Demo_03 {
public static void main(String[] args) throws Exception {
Class c = Student.class;
// 1、反射调用 无参方法
Student s = (Student) c.newInstance();
// 反射调用无参方法,先获取到方法对象
// name:方法名
// parameterTypes:调用这个方法要传的参数类型
Method m1 = c.getMethod("hello");
// invoke:方法的返回值
// obj:类示例
// args:参数值
Object invoke = m1.invoke(s);
System.out.println(invoke);
}
}
输出结果:
2、公有有参
public class Demo_03 {
public static void main(String[] args) throws Exception {
Class c = Student.class;
// 1、反射调用 无参方法
Student s = (Student) c.newInstance();
// 反射调用无参方法,先获取到方法对象
// name:方法名
// parameterTypes:调用这个方法要传的参数类型
Method m1 = c.getMethod("hello");
// invoke:方法的返回值
// obj:类示例
// args:参数值
Object invoke = m1.invoke(s);
System.out.println(invoke);
// 2、调用有参方法
Method m2 = c.getMethod("hello", String.class);
Object invoke2 = m2.invoke(s, "asdfghjk");
System.out.println(invoke2);
}
}
输出结果:
3、私有有参
public class Demo_03 {
public static void main(String[] args) throws Exception {
Class c = Student.class;
// 1、反射调用 无参方法
Student s = (Student) c.newInstance();
// 反射调用无参方法,先获取到方法对象
// name:方法名
// parameterTypes:调用这个方法要传的参数类型
Method m1 = c.getMethod("hello");
// invoke:方法的返回值
// obj:类示例
// args:参数值
Object invoke = m1.invoke(s);
System.out.println(invoke);
// 2、调用有参方法
Method m2 = c.getMethod("hello", String.class);
Object invoke2 = m2.invoke(s, "asdfghjk");
System.out.println(invoke2);
// 3、调用有参私有的方法
Method m3 = c.getDeclaredMethod("add", Integer.class, Integer.class);
// 打开私有权限
m3.setAccessible(true);
Object invoke3 = m3.invoke(s, 1, 2);
System.out.println(invoke3);
}
}
输出结果:
完整代码:
package com.tgq.reflect;
import java.lang.reflect.Method;
/**
* 反射动态方法的调用
*
* @author tgq
*
*/
public class Demo_03 {
public static void main(String[] args) throws Exception {
Class c = Student.class;
// 1、反射调用 无参方法
Student s = (Student) c.newInstance();
// 反射调用无参方法,先获取到方法对象
// name:方法名
// parameterTypes:调用这个方法要传的参数类型
Method m1 = c.getMethod("hello");
// invoke:方法的返回值
// obj:类示例
// args:参数值
Object invoke = m1.invoke(s);
System.out.println(invoke);
// 2、调用有参方法
Method m2 = c.getMethod("hello", String.class);
Object invoke2 = m2.invoke(s, "asdfghjk");
System.out.println(invoke2);
// 3、调用有参私有的方法
Method m3 = c.getDeclaredMethod("add", Integer.class, Integer.class);
// 打开私有权限
m3.setAccessible(true);
Object invoke3 = m3.invoke(s, 1, 2);
System.out.println(invoke3);
}
}
五、反射:读写属性
通过Field类的get()和set()方法来实现。
拿到我们所有的属性:
public class Demo_04 {
public static void main(String[] args) throws Exception {
Class c = Student.class;
Student stu = new Student("1", "1A");
// 我们把age设置一个值
stu.age = 18;
// System.out.println(stu.getSid());
// 获取对象中全部的属性
Field[] fields = c.getDeclaredFields();
// 遍历
for (Field f : fields) {
// 因为sid、sname是私有的,所以我们要打开私有权限
f.setAccessible(true);
// 获取所有属性
System.out.println(f.getName() + ":" + f.get(stu));
}
}
}
输出结果:
我们进行设置属性值:
public class Demo_04 {
public static void main(String[] args) throws Exception {
Class c = Student.class;
Student stu = new Student("1", "1A");
// 我们把age设置一个值
stu.age = 18;
// System.out.println(stu.getSid());
// 拿到属性
Field snamefield = c.getDeclaredField("sname");
// 打开权限
snamefield.setAccessible(true);
// 进行设置
snamefield.set(stu, "2B");
// 获取对象中全部的属性
Field[] fields = c.getDeclaredFields();
// 遍历
for (Field f : fields) {
// 因为sid、sname是私有的,所以我们要打开私有权限
f.setAccessible(true);
// 获取所有属性
System.out.println(f.getName() + ":" + f.get(stu));
}
}
}
输出结果:
完整代码:
package com.tgq.reflect;
import java.lang.reflect.Field;
/**
* 反射:读写属性
*
* @author tgq
*
*/
public class Demo_04 {
public static void main(String[] args) throws Exception {
Class c = Student.class;
Student stu = new Student("1", "1A");
// 我们把age设置一个值
stu.age = 18;
// System.out.println(stu.getSid());
// 拿到属性
Field snamefield = c.getDeclaredField("sname");
// 打开权限
snamefield.setAccessible(true);
// 进行设置
snamefield.set(stu, "2B");
// 获取对象中全部的属性
Field[] fields = c.getDeclaredFields();
// 遍历
for (Field f : fields) {
// 因为sid、sname是私有的,所以我们要打开私有权限
f.setAccessible(true);
// 获取所有属性
System.out.println(f.getName() + ":" + f.get(stu));
}
}
}