获取Class对象
反射常见作用
bean.User
package bean;
public class User {
private int id;
private int age;
private String uname;
public User(){
}
public User(int id, int age, String uname) {
this.id = id;
this.age = age;
this.uname = uname;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getUname() {
return uname;
}
public void setUname(String uname) {
this.uname = uname;
}
}
package reflect;
// 测试各种类型(class,interface,enum,annotation,primitive type,void)对应的java.lang.Class对象的获取方式
public class Demo01 {
public static void main(String[] args) {
String path = "bean.User";
try {
Class clz = Class.forName(path);
// 对象是表示和封装一些数据, 一个类被加载后,JVM会创建一个对应类的Class对象, 类的整个结构信息会放到对应的Class对象中
// 这个Class对象就像一面镜子一样, 通过这面镜子可以看到类的全部信息
System.out.println(clz);
Class strClz = String.class;
Class strClz2 = "".getClass(); // 对象.getClass();
System.out.println(strClz == strClz2); // true
Class intClass = int.class;
int[] arr01 = new int[10];
int[] arr02 = new int[30];
int[][] arr03 = new int[30][3];
double[] arr04 = new double[10];
System.out.println(arr01.getClass().hashCode());
System.out.println(arr02.getClass().hashCode());
System.out.println(arr03.getClass().hashCode());
System.out.println(arr04.getClass().hashCode());
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
应用反射的API, 获取类的信息(类的名字, 属性, 构造器等)
package reflect;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
/**
* 应用反射的API, 获取类的信息(类的名字, 属性, 构造器等)
*/
public class Demo02 {
public static void main(String[] args) {
String path = "bean.User";
try {
Class clz = Class.forName(path);
// 获取类的名字
System.out.println(clz.getName()); // 获取包名+类名
System.out.println(clz.getSimpleName()); // 获取类名
// 获取属性信息
Field[] fields = clz.getFields(); // 只能获取public的field
fields = clz.getDeclaredFields(); // 获得所有的field
Field field = clz.getDeclaredField("uname"); // 获取指定的field
System.out.println(fields.length);
for (Field temp: fields) {
System.out.println("属性: " + temp);
}
// 获取方法信息
Method[] methods = clz.getDeclaredMethods();
// 如果方法有参数, 则必传参数类型对应的Class对象
Method m01 = clz.getDeclaredMethod("getUname", null);
// 方法名, 参数类型对象的Class对象(防止重载)
Method m02 = clz.getDeclaredMethod("setUname", String.class);
for (Method m: methods) {
System.out.println("方法: " + m);
}
// 获得构造方法信息
Constructor[] constructors = clz.getDeclaredConstructors();
Constructor c = clz.getDeclaredConstructor(null);
c = clz.getDeclaredConstructor(int.class, int.class, String.class);
System.out.println(c);
for (Constructor temp: constructors) {
System.out.println("构造方法: " + temp);
}
}catch (Exception e){
e.printStackTrace();
}
}
}
通过反射API动态的操作:构造器,方法,属性
package reflect;
import bean.User;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
/**
* 通过反射API动态的操作:构造器,方法,属性
*/
public class Demo03 {
public static void main(String[] args) {
String path = "bean.User";
try {
Class clz = Class.forName(path);
// 通过动态调用构造方法,构造对象
User u = (User) clz.getDeclaredConstructor().newInstance();
System.out.println(u);
// 有参数构造
Constructor<User> c = clz.getDeclaredConstructor(int.class, int.class, String.class);
User u2 = c.newInstance(1001, 19, "xiaobo");
System.out.println(u2.getUname());
// 通过反射API调用普通方法
User u3 = (User)clz.newInstance();
Method method = clz.getDeclaredMethod("setUname", String.class);
method.invoke(u3, "xiaoli"); // u3.setUname("xiaoli");
System.out.println(u3.getUname());
// 通过反射API操作属性
User u4 = (User)clz.newInstance();
Field f = clz.getDeclaredField("uname");
f.setAccessible(true); // 这个属性不需要做安全检查了,可以直接访问
f.set(u4, "xiaomei"); // 通过反射直接写属性
System.out.println(u4.getUname());
System.out.println(f.get(u4)); // 通过反射直接读属性
}catch (Exception e){
e.printStackTrace();
}
}
}
反射机制性能
反射操作泛型
package reflect;
import bean.User;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;
/**
* 通过反射获取泛型信息
*/
public class Demo04 {
public void test01(Map<String, User> map, List<User> list){
System.out.println("Demo04.test01()");
}
public Map<Integer, User> test02(){
System.out.println("Demo04.test02()");
return null;
}
public static void main(String[] args) {
try {
// 获得指定方法参数泛型信息
Method m = Demo04.class.getMethod("test01", Map.class, List.class);
Type[] t = m.getGenericParameterTypes();
for (Type paramType: t) {
System.out.println("#" + paramType);
if (paramType instanceof ParameterizedType){
Type[] genericTypes = ((ParameterizedType) paramType).getActualTypeArguments();
for (Type genericType: genericTypes) {
System.out.println("泛型类型:" + genericType);
}
}
}
// 获得指定方法返回值泛型类型
Method m2 = Demo04.class.getMethod("test02", null);
Type returnType = m2.getGenericReturnType();
if (returnType instanceof ParameterizedType){
Type[] genericTypes = ((ParameterizedType) returnType).getActualTypeArguments();
for (Type genericType: genericTypes) {
System.out.println("返回值, 泛型类型:" + genericType);
}
}
}catch (Exception e){
e.printStackTrace();
}
}
}
反射操作注解(annotation)
动态编译
JavaComplier动态编译
动态运行
package dynamicCompiler;
import javax.tools.JavaCompiler;
import javax.tools.ToolProvider;
import java.io.*;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
public class Demo01 {
public static void main(String[] args) throws IOException {
// 通过IO流操作,将字符串存储成一个临时文件(Hi.java), 然后调用动态编译方法
String str = "public class Hi{public static void main(String[] args){System.out.println(\"Hello World\");}}";
FileOutputStream os = new FileOutputStream("Hi.java");
os.write(str.getBytes());
os.flush();
os.close();
// 获得java编译器
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
// int result = compiler.run(null, null, null, "/home/sweetheart/eclipse-workspace/Test01/src/HelloWorldAWT.java");
int result = compiler.run(null, null, null, "./Hi.java");
System.out.println(result==0? "编译成功": "编译失败");
// 通过Runtime调用执行类
Runtime run = Runtime.getRuntime();
Process process = run.exec("java -cp ./ Hi");
InputStream in = process.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
String info = "";
while ((info=reader.readLine())!=null){
System.out.println(info);
}
// 通过反射进行加载调用
try {
URL[] urls = new URL[]{
new URL("file:/" + "home/sweetheart/IdeaProjects/annotation/")};
URLClassLoader loader = new URLClassLoader(urls);
Class c = loader.loadClass("Hi");
// 调用加载类的main方法
Method m = c.getMethod("main", String[].class);
m.invoke(null, (Object)new String[]{
"aa", "bb"});
// 不加Object强转相当于这样调用
// public static void main("aa", "bb"){..};
}catch (Exception e){
e.printStackTrace();
}
}
}