java-反射
反射介绍:
- 反射java语言中的一种机制,通过这种机制可以动态的实例化对象、读写属性、调用方法
百分之90的框架都用到了反射;
类类
反射的相关代码都跟以下几个包相关:
- java.lang.Class
- java.lang.reflect.Method
- java.lang.reflect.Field
- java.lang.reflect.construct
这是Student.java封装类,下面的案例操作的类
package com.hyf.reflect;
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());
}
}
获取类对象的方式
- Class.forName(“路径名”); jdbc/自定义mvc框架
- 类名.class ; 结合泛型做通用分页查询方法会用
- 类实例的类实例的getClass()获取 通用的增删改结合泛型使用
代码如下:
package com.hyf.reflect;
public class Demo1 {
public static void main(String[] args) throws Exception {
//1.Class.forName("路径名"); jdbc/自定义mvc框架
// Class stuClz=Class.forName("com.hyf.reflect.Student");
//2 类名.class 结合泛型做通用分页查询方法会用
// Class stuClz=Student.class;
//3.类实例的类实例的getClass()获取
Student s=new Student();
Class stuClz =s.getClass();
System.out.println(stuClz);
}
}
利用反射进行对象实例化
优势:
- 能够对未知的对象进行实例化
- 能够对私有构造器实例化对象
代码演示:
- 调用无参构造器去实例化对象
package com.hyf.reflect;
import java.lang.reflect.Constructor;
public class Demo2 {
public static void main(String[] args) throws Exception{
Class<Student> stuC=Student.class;
// newInsTance 这个方法默是默认使用无参构造器去实例化对象
Student s2 = (Student) stuC.newInstance();
}
}
输出:
调用有参构造器去实例化对象
下方的代码是调用两个参数的方法,如果只调用一个有参的方法就在(stuC.getConstructor(String.class))只写一个。
package com.hyf.reflect;
import java.lang.reflect.Constructor;
public class Demo2 {
public static void main(String[] args) throws Exception{
Class<Student> stuC=Student.class;
Constructor<Student> constructor =stuC.getConstructor(String.class,String.class);
Student stu2=constructor.newInstance("1","八戒");
}
}
输出:
调用私有的构造方法
常会出现的几个错误:
- java.lang.NoSuchMethodException: 没用找到匹配的方法
- java.lang.IllegalAccessException: 没有权限 解决:.setAccessible(true);打开权限 , 默认为false
Class com.hyf.reflect.Demo2 can not access a member of class com.hyf.reflect.Student with modifiers “private”
package com.hyf.reflect;
import java.lang.reflect.Constructor;
public class Demo2 {
public static void main(String[] args) throws Exception{
Class<Student> stuC=Student.class;
Constructor<Student> declaredConstructo=stuC.getDeclaredConstructor(Integer.class);
declaredConstructo.setAccessible(true);// 权限:默认为false
declaredConstructo.newInstance(18);
}
}
输出:
动态方法调用
-
所需的包 java.lang.reflect.Method;
-
动态调用方法
Method m;
m.invoke
package com.hyf.reflect;
import java.lang.reflect.Method;
/**
* 动态方法调用
* @author 17628
*/
public class Demo3 {
public static void main(String[] args) throws Exception {
Student s = new Student();
Class sc = s.getClass();
// 调用无参的方法
System.out.println("无参");
Method m1 = sc.getDeclaredMethod("hello");
m1.invoke(s);
System.out.println("");
// 调用有参的方法
System.out.println("有参");
Method m2=sc.getDeclaredMethod("hello", String.class);
m2.invoke(s, "悟空");
System.out.println("");
// 调用私有方法
System.out.println("私有方法");
Method m3 = sc.getDeclaredMethod("add", Integer.class, Integer.class);
m3.setAccessible(true);
// Method.invoke的返回值是被动态调用的方法的返回值
Object invoke = m3.invoke(s, 12,12);
System.out.println(invoke);
}
}
输出:
反射读取属性
- 需要的包: java.lang.reflect.Field
读取单个属性
package com.hyf.reflect;
import java.lang.reflect.Field;
/**
* 反射读取属性: 自定义标签库。通用分页、自定义mvc 这些需要用到;
*/
public class Demo4 {
public static void main(String[] args) throws Exception, SecurityException {
Student s = new Student("110", "黑猫警长");
s.age = 18;
Class<? extends Student> sc = s.getClass();
Field f = sc.getDeclaredField("sname");
f.setAccessible(true);
System.out.println(f.get(s));
}
}
输出:
(小提示:私有的属性也可以读取)
获取当前Student实例中 s 的所有属性以及属性值
package com.hyf.reflect;
import java.lang.reflect.Field;
public class Demo4 {
public static void main(String[] args) throws Exception, SecurityException {
Student s = new Student("110", "黑猫警长");
s.age = 18;
Class<? extends Student> sc = s.getClass();
// 获取当前Student实例中 s 的所有属性以及属性值
Field [] f=sc.getDeclaredFields();
for (Field field : f) {
field.setAccessible(true); // 打开权限
System.out.println(field.getName()+"--"+field.get(s));
}
}
}