可以操作字节码文件
java.lang.reflect.*;
java.lang.Class 代表字节码文件
java.lang.reflect.Method 代表字节码中的方法的字节码
java.lang.reflect.Constructor 代表字节码中的构造器的字节码
java.lang.reflect.Field 代表字节码中的属性的字节码
获取类的字节码
第一种方式:使用静态方法Class.forName(完整类名加包名)
Class c1 = Class.forName("java.lang.String");Class.forName("java.lang.String");会导致类加载,即执行一次,String方法中的静态代码块也会执行一次,如果想一个类的静态方法执行一次,那么可以使用Class.forName()
第二种方式:使用Object类中的引用.getClass()方法
String s = "abc"; Class c = s.getClass();第三种方式:java中的任意数据类型(包括基本数据类型)都有class属性
Class c = String.class; Class c = int.class;通过字节码文件来实例化对象
public class Test { public static void main(String[] args) { Class c = null; try { //通过反射机制获取字节码文件 c = Class.forName("User"); //newInstacnce()方法会调用User的无参构造方法来new一个User对象 //必须保证User的无参构造方法存在! Object o = c.newInstance(); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } } } class User{ }注意:使用这种方法来初始化对象,更灵活!
举个例子
配置文件
//classinfo.Properties className=com.sdut.wwg.UserUser类
package com.sdut.wwg; public class User { @Override public String toString() { return "User{}"; } }Test类
import java.io.FileReader; import java.util.Properties; public class Test { public static void main(String[] args) throws Exception{ //还可以这样获取绝对路径 /* String path = Thread.currentThread().getContextClassLoader() .getResource("classinfo.Properities").getPath(); 还可以直接返回一个流 InputStream r =Thread.currentThread().getContextClassLoader() .getResourceAsStream("classinfo.Properities"); */ FileReader r = new FileReader("Demo/src/classinfo.Properities"); Properties p = new Properties(); p.load(r); r.close(); String className = p.getProperty("className"); //通过反射机制获取字节码文件 Class c= Class.forName(className); //newInstacnce()方法会调用User的无参构造方法来new一个User对象 //必须保证User的无参构造方法存在! Object o = c.newInstance(); System.out.println(o); } }这样的优点在于当服务器运行的时候,可以直接修改配置文件,而不需要改代码情况下可以做到不同对象的实例化
通过反射机制来反编译一个类的属性(了解)
import java.lang.reflect.Field; import java.lang.reflect.Modifier; public class Test { public static void main(String[] args) throws Exception{ Class c = Class.forName("User"); StringBuffer s= new StringBuffer(); //获取类的修饰符列表和类名 s.append(Modifier.toString(c.getModifiers())+" class "+c.getSimpleName()+"{\n"); Field[] fields = c.getDeclaredFields(); for(Field f:fields){ s.append("\t"); s.append(Modifier.toString(f.getModifiers())+" "); s.append(f.getType().getSimpleName()+" "); s.append(f.getName()+";\n"); } s.append("}"); System.out.println(s); } }输出结果为
通过访问机制来访问一个java对象的属性
import java.lang.reflect.Field; public class Test { public static void main(String[] args) throws Exception{ Class c = Class.forName("User"); Object o = c.newInstance(); //获取no属性 Field noField = c.getDeclaredField("no"); //给o对象的no属性赋值 noField.set(o,1111); //读取属性的值 System.out.println(noField.get(o)); //可以访问私有属性吗?? Field nameField = c.getDeclaredField("name"); //需要打破封装.这样设置完之后,在外部也是可以访问私有属性的 nameField.setAccessible(true); nameField.set(o,"jack"); System.out.println(nameField.get(o)); } }反射方法
public class Test { public static void main(String[] args) throws Exception{ Class c = Class.forName("User"); //获取所有的方法 Method[] methods = c.getDeclaredMethods(); //获取获取到的方法数量 System.out.println(methods.length); for(Method m:methods){ //输出方法的修饰符列表 System.out.print(Modifier.toString(m.getModifiers())+" "); //输出方法的返回值类型 System.out.print(m.getReturnType().getSimpleName()+" "); //输出方法的名字 System.out.println(m.getName()); //获取参数 Class [] ctypes = m.getParameterTypes(); for(Class clas: ctypes){ //输出参数的类型 System.out.println(clas.getSimpleName()); } } } }反编译方法名和参数列表
import java.lang.reflect.Method; import java.lang.reflect.Modifier; public class Test { public static void main(String[] args) throws Exception{ StringBuffer s = new StringBuffer(); Class c = Class.forName("java.lang.String"); Method [] methods = c.getDeclaredMethods(); for(Method m: methods){ s.append('\t'); s.append(Modifier.toString(m.getModifiers())+" "+m.getReturnType().getSimpleName()+" "+m.getName()); s.append(" ("); Class []classes = m.getParameterTypes(); for(Class cls : classes){ s.append(cls.getSimpleName()+','); } if(classes.length>0) s.deleteCharAt(s.length()-1); s.append(") { }\n"); } System.out.println(s); } }输出结果为
通过反射机制调用方法
import java.lang.reflect.Method; public class Test { public static void main(String[] args) throws Exception{ Class userClass = Class.forName("User"); //创建一个User类对象 Object o = userClass.newInstance(); //获取sum方法 Method sum = userClass.getDeclaredMethod("sum", int.class, int.class); //调用sum方法 int result =(int)sum.invoke(o,1,2); System.out.println(result); } }
通过反射机制调用有参构造方法
import java.lang.reflect.Constructor; public class Test { public static void main(String[] args) throws Exception{ Class userClass = Class.forName("User"); //调用无参构造方法创建对象 Object o = userClass.newInstance(); //调用有参构造方法创建对象 Constructor constructor = userClass.getConstructor(int.class,String.class); Object o1 = constructor.newInstance(1111,"jack"); System.out.println(o); System.out.println(o1); } }输出结果为
通过反射机制获取父类以及实现了什么接口
public class Test { public static void main(String[] args) throws Exception{ Class stringClass = Class.forName("java.lang.String"); //获取父类名 Class superClass = stringClass.getSuperclass(); System.out.println(superClass.getSimpleName()); //获取实现了什么接口 Class[] interfaces = stringClass.getInterfaces(); for(Class i:interfaces){ System.out.println(i.getSimpleName()); } } }输出结果