反射的概念
JAVA反射机制是在运行状态中,对于任意一个实体类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。
我们创建对象的方式: Date date = new Date(); 在编译阶段类型是确定的; 反射可以提供运行期创建对象的方式. 客车: 在车站里载人, 静态的; 运行期是客车在路上正在运行: 上个人. java程序如何在运行期创建对象并调用方法, 调用方法才可以获取对象的功能.
反射在java的框架中都得到深入的使用, mybatis,Spring 核心框架技术都是基于反射的技术.
反射的基础
从哪里开始进行反射的操作? 生活中反射的意思: 镜子可以反射出对象的信息: 张书峰站长镜子面前可以反射出张书峰的信息: 身高, 性别, 眨眼(动作). 我们要有一个镜子, 第二要有反射的对象. 镜子是最关键的东西, 回到程序: 我们发现所有的java程序都由类组成的. 镜子要能够描述类的信息.有一个类叫Class就是一面镜子. There is a class named Class.
反射的对象
package com.hanker.reflection;
import java.io.Closeable;
import java.io.IOException;
import java.io.Serializable;
import java.util.Arrays;
/**
* 被反射的对象
* @author Administrator
* @Title: Student.java
* All rights Reserved, Designed By www.hanker.com
* @date: 2020年1月2日 下午2:26:51
* @version V1.0
* @Copyright: 2020 www.hanker.com Inc. All rights reserved.
* 注意:本内容仅限于河南汉科网络信息技术股份有限公司内部传阅,禁止外泄以及用于其他的商业目
*/
public class Student implements Serializable,Closeable {
//2 + 8 + 16
private static final long serialVersionUID = 1L;
private String name;
public int age;
protected double height;
public static void main(String[] args) {
System.out.println(Arrays.toString(args));
Student s = new Student("古力娜扎",35,1.63);
s.print();
}
public void print() {
System.out.println("姓名:"+name);
System.out.println("年龄:"+age);
System.out.println("身高:"+height);
}
public int work(int hours,int money) {
int salary = hours*money;
return salary;
}
public Student() {
super();
System.out.println("====调用无参构造方法=====");
}
public Student(String name, int age, double height) {
super();
System.out.println("====调用有参构造方法=====");
this.name = name;
this.age = age;
this.height = height;
}
public String getName() {
System.out.println("==调用getName方法==");
return name;
}
public void setName(String name) {
System.out.println("==调用setName方法==");
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public double getHeight() {
return height;
}
public void setHeight(double height) {
this.height = height;
}
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + ", height=" + height + "]";
}
@Override
public void close() throws IOException {
}
}
//============================
package com.hanker.reflection;
public class Teacher {
private String name;
public void teach() {
System.out.println(name + "在教学.....");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Class简介
public final class Class<T> extends Object
implements Serializable, GenericDeclaration, Type, AnnotatedElement
Class类是反射的基础, 是一面镜子. 如何获取Class类型的对象. 然后才可以获取类的各种信息,并且可以调用方法.
获取Class的方式
通过对象getClass方法获取
private static void test1() {
//如果类型名称知道,还有对象名,就不用通过反射获取类的信息
Student student = new Student();
Class<? extends Student> class1 = student.getClass();
//可以获取Student类的相关信息
String name = class1.getName();
System.out.println("类的名称:"+name);
}
通过Class.forName获取
/**
* 万物皆对象
* Student---->学生
* Computer--->电脑
* File------->电脑的文件信息
* Math------->数学相关的信息
* Class------>java的字节码文件,所有的类的信息
* Field------>类的属性信息
* Method----->类的方法信息
* Constructor->类的构造方法信息
* @param args
* @throws ClassNotFoundException
*/
public static void main(String[] args) throws ClassNotFoundException {
/**
* clazzName 是对象名, 谁的对象:Class类型的对象
* 这个对象描述信息是谁的? Student
*/
String className = "com.hanker.reflection.Student";
Class<?> clazzName = Class.forName(className);
System.out.println("类名:"+clazzName.getName());
}
通过Type属性获取
private static void test2() {
//前提条件是知道类名称,这样也不用反射
Class<Integer> intClass = Integer.TYPE;
System.out.println("类名:"+intClass.getName());
System.out.println("简单的类名:"+intClass.getSimpleName());
System.out.println("类型名称:"+intClass.getTypeName());
}
通过类名获取Class对象
private static void test3() {
//还是要知道类名,如果知道类名就可以创建对象调用方法,就没有反射的必要
Class<Student> clazz = Student.class;
Class<? super Student> superclass = clazz.getSuperclass();
System.out.println("父类:"+superclass.getName());
Class<?>[] interfaces = clazz.getInterfaces();
for (int i = 0; i < interfaces.length; i++) {
System.out.println("实现的接口: " + interfaces[i]);
}
}
反射类的信息
private static void test4() throws ClassNotFoundException {
/**
* clazzName 是对象名, 谁的对象:Class类型的对象
* 这个对象描述信息是谁的? Student
*/
String className = "com.hanker.reflection.Student";
Class<?> clazzName = Class.forName(className);
System.out.println("类名:"+clazzName.getName());
System.out.println("简单的类名:"+clazzName.getSimpleName());
System.out.println("父类:"+clazzName.getSuperclass().getName());
Class<?>[] interfaces = clazzName.getInterfaces();
for (int i = 0; i < interfaces.length; i++) {
System.out.println("实现的接口: " + interfaces[i]);
}
System.out.println("类所在的包:"+clazzName.getPackage().getName());
System.out.println("类的访问修饰符:"+clazzName.getModifiers());
}
反射创建对象
public static void main(String[] args) throws Exception {
// Student stu = new Student();
String className = "com.hanker.reflection.Student";
Class<?> clazz = Class.forName(className);
//调用对应类型的无参构造方法,必须有无参构造方法,并且不能是私有的private
Object obj = clazz.newInstance();
//调用toString方法
System.out.println(obj);
}
反射属性信息
private static void test1() throws ClassNotFoundException, NoSuchFieldException {
String clazzName="com.hanker.reflection.Student";
Class clazz = Class.forName(clazzName);
//获取所有的属性信息
Field[] fields = clazz.getFields();//获取所有的共有的属性
System.out.println(fields.length);
Field[] df = clazz.getDeclaredFields();//获取所有属性
System.out.println(df.length);
for (Field field : df) {
System.out.println("属性名称:"+field.getName()+
"类型:"+field.getType()+
"修饰符:"+field.getModifiers());
}
//获取指定属性
Field nameField = clazz.getDeclaredField("name");
System.out.println("name属性 :" +nameField);
}
获取属性的目的是绑定值, 如何调用属性的方法:
public static void main(String[] args) throws Exception {
//默认私有属性没有权限访问
String clazzName="com.hanker.reflection.Student";
Class clazz = Class.forName(clazzName);
Object obj = clazz.newInstance();
Field nameField = clazz.getDeclaredField("name");
nameField.setAccessible(true);//强制执行,破门而入
nameField.set(obj, "迪丽热巴");
System.out.println("获取属性值:"+nameField.get(obj));
//set方法和get方法并不是调用的属性对应的getter和setter方法
}
反射构造方法信息
private static void test3() throws Exception {
String clazzName="com.hanker.reflection.Student";
Class clazz = Class.forName(clazzName);
//获取所有的构造方法:共有的
Constructor[] constructors = clazz.getConstructors();
for (Constructor constructor : constructors) {
System.out.println("构造方法:"+constructor);
}
//获取无参构造方法
Constructor c = clazz.getConstructor();
Object obj = c.newInstance();
//获取有参构造器
Constructor c2 = clazz.getConstructor(String.class,int.class,double.class);
Object obj2 = c2.newInstance("迪丽热巴",27,1.65);
System.out.println(obj2);
}
反射普通方法信息
private static void test1() throws Exception {
String clazzName="com.hanker.reflection.Student";
Class clazz = Class.forName(clazzName);
//获取所有的方法:公有私有,只是当前类声明的
System.out.println("==========获取当前类方法===========");
Method[] methods = clazz.getDeclaredMethods();
for (Method method : methods) {
System.out.println(method);
}
System.out.println("==========获取所有方法包括父类===========");
//当前类和父类的方法
Method[] methods2 = clazz.getMethods();
for (Method method : methods2) {
System.out.println(method);
}
//获取指定方法
System.out.println("========获取指定方法==========");
Method workMethod = clazz.getMethod("work", int.class,int.class);
System.out.println(workMethod);
}
调用方法:
private static void test2() throws Exception {
String clazzName="com.hanker.reflection.Student";
Class clazz = Class.forName(clazzName);
Object obj = clazz.newInstance();//创建对象
Method workMethod = clazz.getMethod("work", int.class,int.class);
//必须有对象,注意传对应的参数
Object result = workMethod.invoke(obj, 10,100);
System.out.println("应付工资:"+result);
}
反射main方法信息
private static void test3() throws Exception {
String clazzName="com.hanker.reflection.Student";
Class clazz = Class.forName(clazzName);
Method mainMethod = clazz.getMethod("main", String[].class);
//main方法不用对象,传的是null
mainMethod.invoke(null, new Object[]{new String[] {"a","b","c"}});
}
反射越过泛型检查
package com.hanker.reflection;
import java.lang.reflect.Method;
import java.util.ArrayList;
//反射越过泛型检查
public class GeneralricDemo {
public static void main(String[] args) throws Exception {
ArrayList<String> list = new ArrayList<>();
list.add("this");
list.add("is");
//strList.add(5);//报错
/********** 越过泛型检查 **************/
//获取ArrayList的Class对象,反向的调用add()方法,添加数据
Class listClass = list.getClass();
//获取add()方法
Method m = listClass.getMethod("add", Object.class);
//调用add()方法
m.invoke(list, 5);
//遍历集合
for(Object obj : list){
System.out.println(obj);
}
}
}
反射获取泛型信息
package com.hanker.reflection;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
//反射越过泛型检查
public class GeneralricDemo {
public void test01(Map<String,Student> map,List<Teacher> list) {
System.out.println("方法:test01");
}
public Map<String,Student> test02(){
System.out.println("方法:test02");
return null;
}
public static void main(String[] args) throws Exception {
//根据方法名称和参数类型获取方法
Method method01 = GeneralricDemo.class.getMethod("test01", Map.class,List.class);
//获取该方法的泛型参数类型
Type[] types = method01.getGenericParameterTypes();
for (Type type : types) {
System.out.println("参数:"+type);
Type[] act = ((ParameterizedType)type).getActualTypeArguments();
for (Type t : act) {
System.out.println("真实类型:"+ t);
}
}
System.out.println("==========获取返回值泛型============");
Method m02 = GeneralricDemo.class.getMethod("test02");
//获取方法的泛型类型的返回值
Type retType = m02.getGenericReturnType();
System.out.println("返回值类型:"+retType);
Type[] actualType = ((ParameterizedType)retType).getActualTypeArguments();
for (Type type : actualType) {
System.out.println("\t" + type);
}
}
private static void test1() throws Exception {
ArrayList<String> list = new ArrayList<>();
list.add("this");
list.add("is");
//strList.add(5);//报错
/********** 越过泛型检查 **************/
//获取ArrayList的Class对象,反向的调用add()方法,添加数据
Class listClass = list.getClass();
//获取add()方法
Method m = listClass.getMethod("add", Object.class);
//调用add()方法
m.invoke(list, 5);
//遍历集合
for(Object obj : list){
System.out.println(obj);
}
}
}
反射获取jar包信息
package com.hanker.reflection;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.Enumeration;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
public class ReflectionJarDemo {
public static void main(String[] args) throws Exception {
//1.创建文件
File file = new File("lib/commons-fileupload-1.4.jar");
//2.获取url地址
URL url = file.toURI().toURL();
//创建JarFile对象
JarFile jarFile = new JarFile(file);
Enumeration<JarEntry> entries = jarFile.entries();
StringBuffer buffer = new StringBuffer();
while(entries.hasMoreElements()) {
JarEntry jarf = entries.nextElement();
String classFullName = jarf.getName();
//以class结尾的才是完成类名
if(classFullName.endsWith("class")) {
String className=classFullName.substring(0, classFullName.length()-6).replace("/", ".");
System.out.println(className);
Class<?> clazz = Class.forName(className);
buffer.append("类名:"+className+"\n");
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
buffer.append("属性名:"+field.getName()+",属性类型:" + field.getType()+"\n");
}
Method[] methods = clazz.getDeclaredMethods();
for (Method method : methods) {
buffer.append(method+"\n");
}
}
buffer.append("===============================================");
}
jarFile.close();
//写到文件
BufferedWriter writer = new BufferedWriter(new FileWriter("src/info.txt"));
writer.write(buffer.toString());
writer.close();
}
}
反射创建数组
package com.hanker.reflection;
import java.lang.reflect.Array;
import java.util.Arrays;
public class ArrayReflectionDemo {
//反射背景: 运行中,不知
public static void main(String[] args) {
//int[]arr = new int[10];
Object arr = Array.newInstance(int.class, 10);
//arr[5] = 100
Array.set(arr, 5, 100);//arr是数组名,5下标,100是值
//int num = arr[5]
Object object = Array.get(arr, 5);
System.out.println("=="+Arrays.toString((int[])arr));
System.out.println(object);
}
}
手写Spring框架
student=com.hanker.reflection.Student
teacher=com.hanker.reflection.Teacher
package com.hanker.reflection;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
public class HankerSpring {
public static void main(String[] args) throws Exception {
Object obj = getBean("student");
System.out.println(obj);
Teacher t = (Teacher) getBean("teacher");
t.setName("孔夫子");
t.teach();
}
private static Object getBean(String k) throws Exception {
Map<String,Object> factory = new HashMap<>();//对象工厂
Map<String,String> map = new HashMap<>();//配置文件信息
//创建文件对象
File file = new File("src/hanker_config.txt");
//读取文件
BufferedReader reader = new BufferedReader(new FileReader(file));
while(reader.ready()) {
String line = reader.readLine();//读取一行
String[] data = line.split("=");//分割
map.put(data[0], data[1]);//把分割后的放到map
}
reader.close();//关闭输入流
//遍历Map集合
Set<Entry<String, String>> entrySet = map.entrySet();
for (Entry<String, String> entry : entrySet) {
String key = entry.getKey();//获取key
String value = entry.getValue();//获取value 包名+类名
Class<?> clazz = Class.forName(value);//反射获取clazz对象
Object o = clazz.newInstance();//调用无参构造方法创建对象
factory.put(key,o);//放到对象工厂: key=student value是对象
}
return factory.get(k);//根据key获取对应的对象
}
}
tring line = reader.readLine();//读取一行
String[] data = line.split("=");//分割
map.put(data[0], data[1]);//把分割后的放到map
}
reader.close();//关闭输入流
//遍历Map集合
Set<Entry<String, String>> entrySet = map.entrySet();
for (Entry<String, String> entry : entrySet) {
String key = entry.getKey();//获取key
String value = entry.getValue();//获取value 包名+类名
Class<?> clazz = Class.forName(value);//反射获取clazz对象
Object o = clazz.newInstance();//调用无参构造方法创建对象
factory.put(key,o);//放到对象工厂: key=student value是对象
}
return factory.get(k);//根据key获取对应的对象
}
}