Web基础之Java中的反射机制

时间:2023-02-16 14:08:19
Web基础之Java中的反射

一、Java中的反射机制

反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,

能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。



二、反射机制的功能:

· 在运行时获取任意一个对象所属的类;

· 在运行时构造任意一个类的对象;

· 在运行时获取任意一个类所具有的成员变量和方法;

· 在运行时调用任意一个对象的方法;

· 生成动态代理。(了解)


三、反射API(后面会有代码演示)
通过一个对象或类获取完整的包名和类名
在运行时实例化一个类的对象
获取一个类的父类和实现的接口
获取某个类的全部构造方法
获取某个类的全部属性和方法
通过反射机制调用某个类的方法
通过反射机制操作某个类的属性

四、反射机制的应用
     在泛型为 Integer ArrayList 中存放一个其他类型的对象
     通过反射取得并修改数组的信息
     通过反射机制修改数组的大小
     在 DAO 中,优化对象的封装



五、代码演示Java反射API以及简单应用
新建一个Person类,该类的属性和方法如下;
为了后面的测试,我们实现了序列化接口:
package com.hx.ref;

import java.io.Serializable;

public class Person implements Serializable{

private static final long serialVersionUID = 1L;

public static String schname;

private String name;

private int age;

private String sex;

private float weight;

public Person() {

}

public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}

public Person(String name, int age, String sex, float weight) {
super();
this.name = name;
this.age = age;
this.sex = sex;
this.weight = weight;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}

public String getSex() {
return sex;
}

public void setSex(String sex) {
this.sex = sex;
}

public float getWeight() {
return weight;
}

public void setWeight(float weight) {
this.weight = weight;
}

public String toString() {
String str="Person:"+"Name:"+name+"Age:"+age+"Sex:"+sex+"Weight:"+weight;
return str;
}
}

package com.hx.ref;

import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.List;

public class Test {

public static void main(String[] args) throws Exception{

// String [] str={"123","345","678","789"};
// String [] copyStr=arrayCopyandIncres(str, 2,String.class);
//
// priArray(copyStr);
//
// Integer [] ints={1,2,3,4,5};
// Integer[] inscopy=arrayCopyandIncres(ints, 4, Integer.class);
// priArray(inscopy);

test6();
}

// 获取Person类的Class对象
@SuppressWarnings({ "unused", "rawtypes" })
private static void test1() {
// Class类的获取方法:通过[对象的getClass()方法]获取Class对象
Person p = new Person();
Class clazz = p.getClass();
System.out.println(clazz.getName());

//获取Person类的修饰
int m = clazz.getModifiers();
System.out.println(Modifier.isPublic(m));

// Class类的获取方法:通过对象的[类.class方法]获取Class对象
System.out.println(Person.class.getSimpleName());
System.out.println(Person.class.getName());

// Class类的获取方法:通过Class.forName("+全限定名")获取Class对象
try {
System.out.println(Class.forName("com.hx.ref.Person").getName());
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}

// 通过Class类创建对象
@SuppressWarnings({ "unused", "rawtypes" })
private static void test2() throws InstantiationException,
IllegalAccessException {
Class clazz = Person.class;
Person p = (Person) clazz.newInstance();
System.out.println(p);
}

// 获取Class类的父类以及实现的接口
@SuppressWarnings({ "unused", "rawtypes" })
private static void test3() throws InstantiationException,
IllegalAccessException {
Class clazz = Person.class;
Class supclazz = clazz.getSuperclass();
Class[] intefaces = clazz.getInterfaces();
System.out.println(supclazz);
priArray(intefaces);
}

// 获取Person类构造函数
@SuppressWarnings({ "unused", "rawtypes" })
private static void test4() throws InstantiationException,
IllegalAccessException {
Class clazz = Person.class;
Constructor[] cons = clazz.getConstructors();
priArray(cons);
}

// 获取字段和方法
@SuppressWarnings({ "unused", "rawtypes" })
private static void test5() throws InstantiationException,
IllegalAccessException {
Class clazz = Person.class;
Field[] fiels = clazz.getDeclaredFields();
priArray(fiels);

Method[] methods = clazz.getDeclaredMethods();
priArray(methods);
}

// 获取构造函数并构造对象
@SuppressWarnings({ "unused", "rawtypes" })
private static void test6() throws InstantiationException,
IllegalAccessException, IllegalArgumentException,
InvocationTargetException {
//获取Class类对象
Class clazz = Person.class;
//获取构造函数
Constructor[] cons = clazz.getDeclaredConstructors();
priArray(cons);
//拿到一个构造函数
Constructor c = cons[0];
//获取该构造函数的参数列表的类类型
Class[] paraClazz = c.getParameterTypes();
//如果参数列表为0,则直接new对象
if (paraClazz.length == 0) {
Object o = c.newInstance(new Object[] {});
System.out.println(o);
} else {
// 构建参数列表
Object[] paras = new Object[paraClazz.length];
for (int i = 0; i < paraClazz.length; i++) {
//通过GETVALUE方法,该每个参数列表付初始值
paras[i] = getValue(paraClazz[i]);
}
Object result = c.newInstance(paras);
System.out.println("result:" + result);
}
}

// 操作字段
@SuppressWarnings({ "rawtypes", "unused" })
private static void test7() throws Exception {
Class clazz = Person.class;
//构造实例
Object person = clazz.newInstance();
//获取所有字段
Field[] field = clazz.getDeclaredFields();

//遍历所有属性
for (int i = 0; i < field.length; i++) {
int m = field[i].getModifiers();
//排除Static属性异己非私有属性
if (Modifier.isStatic(m) || !Modifier.isPrivate(m)) {
continue;
}
//拿到属性名字
String fieldname = field[i].getName();
//拼set方法
String setterName = "set"
+ Character.toUpperCase(fieldname.charAt(0));
if (fieldname.length() > 1) {
setterName = setterName + fieldname.substring(1);
}
@SuppressWarnings("unchecked")
//获取set方法
Method m1 = clazz.getDeclaredMethod(setterName,
new Class[] { field[i].getType() });
//通过方法为属性设置值
m1.invoke(person, new Object[] { getValue(field[i].getType()) });
}

System.out.println("person:" + person);
}

// 操作字段2
@SuppressWarnings("unused")
private static void test8() throws InstantiationException,
IllegalAccessException {
@SuppressWarnings("rawtypes")
Class clazz = Person.class;
Object p1 = clazz.newInstance();
Field[] fields = clazz.getDeclaredFields();
for (int i = 0; i < fields.length; i++) {
int m = fields[i].getModifiers();
if (Modifier.isStatic(m) || !Modifier.isPrivate(m)) {
continue;
}
// 破坏了封装性
fields[i].setAccessible(true);
fields[i].set(p1, getValue(fields[i].getType()));
}

System.out.println("p1:" + p1);
}

// 操作数组
@SuppressWarnings("unused")
private static void test9() throws Exception{
List<String> plist = new ArrayList<String>();
plist.add("张三");
plist.add("李四");

Class<?> clazz = plist.getClass();
Method m = clazz.getMethod("add", Object.class);
//说明了泛型只在编译阶段会检查,运行阶段没有泛型一说
m.invoke(plist, new Integer(999));

System.out.println("plist:" + plist);
}

//数组的拷贝
@SuppressWarnings({ "unused", "unchecked" })
private static <T> T[] arrayCopyandIncres(T[] array, int times,Class<T> clazs) {
// 获取数组中的存储类型
Class<?> clazz = array.getClass().getComponentType();
Object newArray = Array.newInstance(clazz, array.length * times);
for (int i = 0; i < array.length; i++) {
Array.set(newArray, i, array[i]);
}
return (T[]) newArray;
}

@SuppressWarnings("rawtypes")
private static Object getValue(Class clazz) {
if (clazz == Boolean.class || clazz == Boolean.TYPE) {
return Boolean.TRUE;
}
if (clazz == Byte.class || clazz == Byte.TYPE) {
return Byte.valueOf((byte) 100);
}
if (clazz == Short.class || clazz == Short.TYPE) {
return Short.valueOf((short) 200);
}
if (clazz == Character.class || clazz == Character.TYPE) {
return Character.valueOf('a');
}
if (clazz == Integer.class || clazz == Integer.TYPE) {
return Integer.valueOf(300);
}
if (clazz == Long.class || clazz == Long.TYPE) {
return Long.valueOf(400L);
}
if (clazz == Float.class || clazz == Float.TYPE) {
return Float.valueOf(50.0F);
}
if (clazz == Double.class || clazz == Double.TYPE) {
return Double.valueOf(100.0);
}
// String 类型
if (clazz == String.class) {
return "Hello";
}
// 如果还没匹配到,那该类型一定是引用类型,返回null
return null;
}


private static void priArray(Object[] obj) {
for (int i = 0; i < obj.length; i++) {
System.out.println(obj[i]);
}
}
}


六、部分运行结果:
Web基础之Java中的反射机制

Web基础之Java中的反射机制

Web基础之Java中的反射机制

Web基础之Java中的反射机制

Web基础之Java中的反射机制

Web基础之Java中的反射机制


七、总结
Java反射是Java中比较高级的知识;第一次接触会有点不可思议;会觉得不太好理解;
我觉得首先的得对反射这块的知识有所了解,然后通过自己写代码掌握好这些反射的API以及使用;
其实反射这块我也花了很长的时间才能慢慢理解;写这篇博客的时候,我已经前后两次接触Java反射了;
今天写博客再次整理这块知识的时候觉得比以前好很多了;
所以,坚持不要放弃,到最后你总会懂的;就像以前初中学知识,我感觉好多地方学得模模糊糊的,后来 来到大学给初中生做家教的时候再去看那些知识,觉得好简单;我觉得这有两个方面的原因:一是随着年龄的增长,自己的理解力变强了;二是因为通过高中的学习以及大学的学习,不断的学习让自己的思维发生了很大的变化;我觉得第二点更能说明;所以,只要坚持不懈的努力学习,任何难点都不会是难点;我们的技术也会越来越强;
共勉!