反射是框架设计的灵魂
一、反射的概述
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
要想解剖一个类,必须先要获取到该类的字节码文件对象。而解剖使用的就是Class类中的方法.所以先要获取到每一个字节码文件对应的Class类型的对象.反射是java语言的一种机制,利用反射机制动态的实例化对象(构造函数)、读写属性、调用方法。
简单来说反射是java语言的一种机制,利用反射机制动态的实例化对象(构造函数)、读写属性、调用方法。
反射就是把java类中的各种成分映射成一个个的Java对象
例如:一个类有:成员变量、方法、构造方法、包等等信息,利用反射技术可以对一个类进行解剖,把个个组成部分映射成一个个对象。
二、反射的使用(这里使用Student类做演示)
1、获取Class对象的三种方式
1.1 Object ——> getClass();
1.2 任何数据类型(包括基本数据类型)都有一个“静态”的class属性
1.3 通过Class类的静态方法:forName(String className)(常用)
其中1.1是因为Object类中的getClass方法、因为所有类都继承Object类。从而调用Object类来获取
先写一个Student类。
package com.zking.reflection;
import java.io.Serializable;
public class Student implements Serializable{
/**
*
*/
private static final long serialVersionUID = 6921501844505269294L;
private String sid;
private String sname;
public Integer age;
public Student() {
System.out.println("调用无参构造方法创建了一个学生对象");
}
public Student(String sid) {
this.sid = sid;
System.out.println("调用带一个参数的构造方法创建了一个学生对象");
}
public Student(String sid, String sname) {
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());
}
@Override
public String toString() {
return "Student [sid=" + sid + ", sname=" + sname + ", age=" + age + "]";
}
}
package com.zking.reflection;
public class Demo01 {
public static void main(String[] args) throws Exception {
//java反射是java中的一种重要机制
//它可以动态的实例化对象,读写属性,调用方法
//一切反射相关的代码都从获得类对象开始
//获得类对象的方式
//1.类名.class
Class clazz = Student.class;
System.out.println(clazz);
System.out.println("-----------------");
//2.对象名.getClass();
Student stu = new Student();//这一new 产生一个Student对象,一个Class对象。
Class clazz1 = stu.getClass();
System.out.println(clazz1);
System.out.println("-----------------");
//3.Class.forName(全限定名/全路径名) 最常用
Class clazz2 = Class.forName("com.zking.reflection.Student");//注意此字符串必须是真实路径,就是带包名的类路径,包名.类名
System.out.println(clazz2);
System.out.println(clazz==clazz1);//判断三种方式是否获取的是同一个Class对象 true
System.out.println(clazz.getSimpleName());//获取类名
System.out.println(clazz.getTypeName());//获取全限定名
System.out.println(clazz.getPackage());//获取包名
}
}
三种方式常用第三种,第一种需要导入类的包,依赖太强,不导包就抛编译错误。第二种对象都有了还要反射干什么。一般都第三种,一个字符串可以传入也可写在配置文件中等多种方法。
2、使用反射实例化对象
package com.zking.reflection;
import java.lang.reflect.Constructor;
public class Demo02 {
public static void main(String[] args) throws Exception {
//java反射是java中的一种重要机制
//它可以动态的实例化对象,读写属性,调用方法
//一切反射相关的代码都从获得类对象开始
//Class.forName(全限定名/全路径名) 最常用
Class clazz = Class.forName("com.zking.reflection.Student");
//实例化对象
// Student stu =(Student)clazz.newInstance();
// System.out.println(stu);
//通过构造方法实例化对象
//1.获取无参公有构造方法对象
// Constructor constructor = clazz.getConstructor();
// //2.实例化对象
// Object obj = constructor.newInstance();
// System.out.println(obj);
// Student stu = new Student("001");
// System.out.println(stu);
//获取有参公有构造方法对象
// Constructor constructor = clazz.getConstructor(String.class,String.class);
// //实例化对象
// Object obj = constructor.newInstance("001","小黄");
// System.out.println(obj);
//获取有参私有构造方法对象
Constructor constructor = clazz.getDeclaredConstructor(Integer.class);
//如果是私有构造方法,必须打开方法的访问限制
constructor.setAccessible(true);
//实例化对象
Object obj = constructor.newInstance(111);
System.out.println(obj);
}
}
3、使用反射读写属性
package com.zking.reflection;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
public class Demo03 {
public static void main(String[] args) throws Exception {
//java反射是java中的一种重要机制
//它可以动态的实例化对象,读写属性,调用方法
//一切反射相关的代码都从获得类对象开始
//Class.forName(全限定名/全路径名) 最常用
Class clazz = Class.forName("com.zking.reflection.Student");
Student stu = (Student)clazz.newInstance();//实例化对象
//读写属性
//1.获取属性对象
Field field = clazz.getDeclaredField("sid");
//2.打开访问限制
field.setAccessible(true);
//3.写属性
field.set(stu, "001");
//4.读属性
Object obj = field.get(stu);
System.out.println(obj.toString());
System.out.println(field.getName());//获取属性名
System.out.println(field.getType());//获取属性类型
System.out.println(field.getModifiers());//获取属性访问修饰符
// Field field=cla.getField(“属性名”);
// field.getName(); -->获取属性名
// filed.getType(); -->获取属性类型
// field.getModifiers(); -->获取属性访问修饰符
// field.set(Object,Object); -->设置属性值,参数1:要设置属性所在对象;参数2:要设置的值;
// field.get(Object); -->获取属性值,参数:要获取属性值的对象
// clazz.getDeclaredField(“属性名”); -->获取单个属性(私有、公有、受保护、默认、静态)
// clazz.getDeclaredFields(); -->获取所有属性(私有、公有、受保护、默认、静态)
}
}
4、使用反射调用方法
package com.zking.reflection;
import java.lang.reflect.Method;
public class Demo04 {
public static void main(String[] args) throws Exception {
//java反射是java中的一种重要机制
//它可以动态的实例化对象,读写属性,调用方法
//一切反射相关的代码都从获得类对象开始
//Class.forName(全限定名/全路径名) 最常用
Class clazz = Class.forName("com.zking.reflection.Student");
Student stu = (Student)clazz.newInstance();//实例化对象
stu.setSname("牛马");
//调用方法
//1.获得方法对象
// Method method = clazz.getDeclaredMethod("hello",String.class);
// //2.打开方法访问限制
// method.setAccessible(true);
// //3.调用方法
// method.invoke(stu,"大黄");
//1.获得方法对象
// Method method = clazz.getDeclaredMethod("add",Integer.class,Integer.class);
// //2.打开方法访问限制
// method.setAccessible(true);
// //3.调用方法
// Object invoke = method.invoke(stu,88,99);
// System.out.println(invoke);
//获取类对象中所有实现接口列表
Class[] classes = clazz.getInterfaces();
for (Class class1 : classes) {
System.out.println(class1);
}
//获得父类对象
clazz.getSuperclass();
//无参无返回、无参有返回、有参无返回、有参有返回
// 根据类得到类的方法
// cla.getMethod(); -->获取单个公有方法
// cla.getDeclaredMethod(); -->获取当个方法(包括私有、受保护、默认、公有)
// cla.getMethods(); -->获取所有公有方法
// cla.getDeclaredMethods(); -->获取所有的方法(包括私有、受保护、默认、公有)
// 根据类得到类的构造方法
// cla.getConstrutor(); -->获取单个公有构造方法
// cla.getDeclaredConstrutor();-->获取单个构造方法(包括私有、受保护、默认、公有)
// cla.getConstrutors(); -->获取所有的公有构造方法
// cla.getDeclaredConstrutors();-->获取所有的构造方法(包括私有、受保护、默认、公有)
}
}