反射机制是java的动态性之一
动态性:在程序运行时,可以改变程序的结构和变量的类型。
典型的动态语言“Python、ruby、javaScript”
C,C++,Java不是动态语言,但具有一定的动态性,可以成为“准动态语言”,具备类似动态语言的特性。传一块代码来动态的执行,动态的处理,java也能做,可以利用反射来实现类似的功能。java的动态性让编程变得更加灵活,功能就更加的强大。
反射机制
程序在运行的过程中加载一些“只知道相关名字”的类,以下代码在程序运行时加载User类:Class c = Class.forName(“com.weini.User”);
一个类被加载后,JVM会创建一个对应类的Class对象,类的整个结构信息会被放到Class对象中。这个Class对象就像镜子一样,通过这面镜子,可以得到对应类的全部信息。
反射机制的常见作用
获取Class对象的方式
import come.weini.User;
public class Test {
public static void main(String[] args) throws ClassNotFoundException {
System.out.println(int.class);
System.out.println(void.class);
int []arrA=new int[10];
int[] arrB=new int[30];
/**维数相同和类型相同的数组共享同一个Class对象*/
System.out.println(arrA.getClass()==arrB.getClass());
/**同一个类的N多对象,共享同一个Class对象*/
User u1=new User();
User u2=new User();
System.out.println(u1.getClass()==u2.getClass());
/**获取Class对象的三种方式*/
//(1)通过对象的getClass()方法获取
Class c1=u1.getClass();
//(2)通过字节码文件获取
Class c2=User.class;
//(3)通过Class类的静态方法获取
Class c3=Class.forName("com.weini.User");
System.out.println((c1==c2)+"\t"+(c1==c3));
}
}
public class User {
//类的属性
private int userId;
private String userName;
private String password;
//公有的取值,赋值方法
public int getUserId() {
return userId;
}
public void setUserId(int userId) {
this.userId = userId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
//构造方法
public User() {
// TODO Auto-generated constructor stub
}
public User(int userId, String userName, String password) {
super();
this.userId = userId;
this.userName = userName;
this.password = password;
}
}
获取类的名字
序号 | 方法 | 描述 |
---|---|---|
1 | String getName() | 获取包名+类名 |
2 | String getSimpleName() | 获取类的名字 |
获取类的属性
序号 | 方法 | 描述 |
---|---|---|
1 | Field getField(String fieldName) | 得到公共的属性对象 |
2 | Field getDeclareField(String fieldName) | 得到指定名称的属性对象 |
3 | Field [] c.getDeclaredFields() | 得到所有的属性对象 |
获取类的方法
序号 | 方法 | 描述 |
---|---|---|
1 | Method[] getDeclareMethods() | 得到公共的方法对象 |
2 | Method[] c.getMethods() | 得到父类及本类中的公共方法对象 |
3 | Method getDeclaredMethod(String methodName,Class…type) | 得到指定名称的本类中公共的方法 |
4 | Method getMethod(String methodName,Class type) | 得到本类或父类中的公共的方法对象 |
获取构造方法
序号 | 方法 | 描述 |
---|---|---|
1 | Constructor[] getDeclaredConstructors() | 得到公共的构造方法的对象 |
2 | Constructor[] getConstructors() | 得到公共的构造方法对象 |
3 | Constructor getDeclaredConstructor(Class…type) | 得到指定参数的公共的构造方法对象 |
package com.weini.entity;
public class User {
//类的属性
//public int userId;
private int userId;
private String userName;
private String password;
//公有的取值,赋值方法
public int getUserId() {
return userId;
}
public void setUserId(int userId) {
this.userId = userId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
//构造方法
public User() {
// TODO Auto-generated constructor stub
}
public User(int userId, String userName, String password) {
super();
this.userId = userId;
this.userName = userName;
this.password = password;
}
}
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class Test {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, SecurityException, NoSuchMethodException {
String path="com.weini.entity.User";
//(1)获取类的名称
Class c=Class.forName(path);
System.out.println("类的全名称:"+c.getName());
System.out.println("类的名称:"+c.getSimpleName());
//获取父类的Class对象
Class cSuper=c.getSuperclass();
System.out.println(cSuper.getName());
System.out.println(cSuper.getSimpleName());
//(2)获取类的属性信息
//Field f=c.getField("userId"); //只能获取公共的属性
//System.out.println(f);
Field [] fields=c.getFields(); //只能获取公共的属性
System.out.println(fields.length);
Field [] fields2=c.getDeclaredFields();
//System.out.println(fields2.length);
for (Field field : fields2) {
//System.out.println(field);//调用了toString()方法
System.out.println(field.getModifiers()+"\t"+field.getType()+"\t"+field.getName());
}
//(3)获取类的方法信息
Method[] methods=c.getDeclaredMethods(); //本类中的公共的方法对象
System.out.println(methods.length);
for (Method method : methods) {
//System.out.println(method);
System.out.println("访问权限"+method.getModifiers());
System.out.println("返回值类型:"+method.getReturnType());
System.out.println("方法的名称:"+method.getName());
//获取方法的参数
Class [] cPara=method.getParameterTypes();
for (Class c1 : cPara) {
System.out.println(c1.getTypeName()+"\t");
}
System.out.println("\n--------------------------");
}
System.out.println("\n=============================\n");
//(4)获取类的构造器
Constructor [] cons=c.getConstructors();
for (Constructor constructor : cons) {
System.out.println(constructor);
}
System.out.println("\n=====================");
//获取指定的构造方法
Constructor con=c.getConstructor(null);
System.out.println(con);
System.out.println("\n=====================");
Constructor con2=c.getConstructor(int.class,String.class,String.class);
System.out.println(con2);
}
}
动态的操作属性、方法、构造方法
package com.weini.test;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import com.bjsxt.entity.User;
public class Test2 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchFieldException {
//获到Class类的对象
Class c=Class.forName("com.bjsxt.entity.User");
//(1)得到无参构造方法的对象
Constructor cons=c.getConstructor(null);
//通过无参构造方法的对象,创建User类的对象
User user=(User) cons.newInstance();
//(2)动态操作属性
Field field=c.getDeclaredField("userId");
field.setAccessible(true);//这个属性不需要做安全检查了,可以直接访问
field.set(user, 1001); //通过反射直接赋值
System.out.println("取出userId这个属性的值:"+field.get(user));//通过反射直接取值
//(3)动态操作方法
Method m=c.getDeclaredMethod("setUserName", String.class);
//执行setUserName这个方法
m.invoke(user, "张三");
Method m2=c.getDeclaredMethod("getUserName", null);
System.out.println(m2.invoke(user));
}
}
反射机制对程序的运行在性能上有一定的影响,速度慢
提高反射性能
setAccessible启用和禁用访问安全检查的开关,值为true则指示反射的对象在使用时应该取消java语言访问检查。禁止安全检查可以提高反射的运行速度。
泛型
java中的泛型仅仅是给编译器javac使用的,确保数据的安全性和免去强制类型转换的麻烦,但是一旦编译完成,所有与泛型有关的类型全部擦除。
使用泛型直接读取泛型,是读取不到的,因为反射时操作以后加载的类。
java新增的数据类型
为了通过反射操作这些类型 以迎合实际开发的需要
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;
import com.weini.entity.User;
public class TestGeneric {
public void test01(Map<String,User> map,List<User> list,String s){
System.out.println("TestGeneric.test01()");
}
public Map<Integer,User> test02(){
System.out.println("TestGeneric.test02()");
return null;
}
public String test03(){
System.out.println("TestGeneric.test03()");
return null;
}
public static void main(String[] args) throws NoSuchMethodException, SecurityException {
//获取test01方法的泛型参数信息
Class c=TestGeneric.class;
Method test01=c.getMethod("test01", Map.class,List.class,String.class);
//获取带泛型参数的类型
Type [] tytes=test01.getGenericParameterTypes();
System.out.println(tytes.length);
for (Type type : tytes) {
//System.out.println("#"+type);
if (type instanceof ParameterizedType) {
Type[] genericType= ((ParameterizedType) type).getActualTypeArguments();
//遍历每一个泛型参数中泛型的类型
for (Type genType : genericType) {
System.out.println("泛型类型:"+genType);
}
System.out.println("\n--------------------------");
}
}
System.out.println("\n----------------------------\n");
//获取test02方法返回值的泛型信息
Method m2=c.getMethod("test02", null);
Type returnType=m2.getGenericReturnType();
//判断是否带有泛型
if(returnType instanceof ParameterizedType){
Type [] types=((ParameterizedType) returnType).getActualTypeArguments();
for (Type type : types) {
System.out.println("返回值的泛型类型:"+type);
}
}
System.out.println("\n------------------------------\n");
Method m3=c.getMethod("test03", null);
Type returnType3=m3.getGenericReturnType();
//System.out.println(returnType3);
System.out.println(returnType3 instanceof ParameterizedType);
}
}