java反射
java 1.2反射
java 基础四大接口
Comparable 用于对象比较的接口;
Runnable 用于对象线程话的接口;
Serializable 用于对象序列化的接口;
Clonable 用于对象克隆的接口;
通过反射创建对象
//创建A对象,通过newInstance方法
Object obj6 = Class.forName("A").newInstance();
Method m = Class,forName("A").getMethod("hello");
m.invoke(obj6);
//
Constructor<A> constructor = A.class.getConstructor();
A obj8 = constructor.newInstance();
obj8.hello();
类关键字
Class:类型标识
成员变量、方法、构造函数、修饰符、包、父类、父接口...
// 类成员变量Filed
Class A{
public int age;
private String name;
public A(int age,String name){
this.age = age;
this.name = name;
}
}
//反射
A obj = new A(2,"Tom");
Class c = obj.getClass();
//获取本类及父类所有的public字段
Field[] fs = c.getFields();
//获取本类所有声明的字段
Field[] fs2 = c.getDeclaredFields();
for(Field f : fs2){
//临时将私有方法转化为公有
f.setAccessible(true);
System.out.println(f.getName() + ":" + f.get(obj));
}
//成员方法Method
class B{
public void f1(){
out.printl("B.f1()...");
}
private String f2(String s){
out.println("B.f2()...");
return s;
}
}
//反射
B obj = new B();
Class c = obj.getClass();
//获取public方法 包括父类和父接口
Method[] ms = c.getMethods();
for(Method m : ms){
if("f1".equals(m.getName())){
m.invoke(obj,null);
}
}
//获得该类的所有方法
Method[] ms2 = c.getDeculareMethods();
for(Method m : ms2){
if("f2".equals(m.getName())){
m.setAccessible(true);
String result = (String)m.invoke(obj,"abc");
}
}
//构造函数 Constructor
class D{
private int num;
public D(){
this.num = 10;
}
public D(int num){
this.num = num;
}
public void printNum(){
System.out.println(this.num);
}
}
//反射
D d = new D();
Class c = d.getClass();
Constructor[] cons = c.getConstructor();
for(Constructor con : cons){
if(con.getParameterCount() > 0){
// 有参构造函数
D obj = (D) con.newInstance(100);
obj.printNum();
}else{
// 无参构造函数
D obj = (D) con.newInstance();
obj.printNum();
}
}
//父类、父接口
class Father{}
class Son extends Father implements Cloneable,Comparable{
protected Object clone() throws CloneNotSupportedException{
return super.clone();
}
public int compareTo(Object o){
return o;
}
}
//反射
Son son = new Son();
Class c = son.getClass();
//获取父类(Father)
Class father = c.getSuperclass();
System.out.println(father.getName());
//获取父接口
Class[] inters = c.getInterfaces();
for(Class inter : inters){
System.out.println(inter.getName());
}
反射应用场景
-
数据库连接
// -Connection,连接到各个不同数据库 try{ //通知类加载器加载此类的class文件 class.forName("com.mysql.jdbc.Driver"); }catch(ClassNotFoundException e1){ e1.printStackTrace(); return; } //构建按java 和数据库之间的桥梁:URL,用户名,密码 conn = DriverManager.getConnection(url,"root","123456"); //DriverManager将会挑选加载合适的驱动类,并采用getConnection方法连接 -
数组扩充
给定一个数组(任意类型),将其长度扩大一倍
java的数组一旦创建,其长度是不再更改的
新建的一个大数组(相同类型),然后将旧数组的内容拷贝过去
public static Object goodCopy(Object oldArray, int newLength){ //Array类型 Class c = oldArray.getClass(); //获取数组中的单个元素类型 Class componentType = c.getComponentType(); //旧数组长度 int oldLength= Array.getLength(oldArray); //新数组:创建新数组,数组内元素类型约束为componentType类型,新数组长度为newLength object newArray = Array.newInstance(componentType,newLength); //拷贝旧数据 System.arraycopy(oldArray,0,newArray,0,oldlength); return newArray; } int[] a = {1,2,3,4,5}; a = (int[]) goodcopy(a,10); for(int i : a){ System.out.pringln(i); //1 2 3 4 5 0 0 0 0 0 } -
动态执行方法
给定类名、方法名、即可执行
加上定时器,即可做定时任务执行
class Worker{ public static void hello(){ System.out.println("Hello java!"); } } class MyTest extends TimerTask{ public void run(){ try{ Method m = Class.forName("Worker").getClass().getMethod("hello"); m.invoke(null);// 静态方法可以不用new对象 }catch(Exception e){ e.printStackTrace(); } } } //test Timer timer = new Timer(); Calendar now = Calendar.getInstance(); now.set(Calendar.SECOND,now.get(Calendar.SECOND)+1); Date runDate = now.getTime(); MyTask task2 = new MyTask(); timer.scheduleAtFixeRate(task2,runDate,3000); -
Tomcat的Servlet创建
<!-- web.xml--> <!-- servlet definition--> <servlet> <servlet-name>Init</servlet-name> <servket-class>service.Init</servket-class> </servlet>public Object newInstance(final String classNmae,final ClassLoader classloader) throws IllegalAccessException,NamingException,InvocationTargetException,InstantiationException,ClassNotFoundException,IllegalArgumentExcption,NoSuchMethodException,SecurityException{ Class<?> clazz = classLoader.loadClass(className); return newInstance(clazz.getConstructor().newInstance(),clazz); }备注: Class.forName(className)方法,内部实际调用的方法是 Class.forName(className,true,classloader); 第2个boolean参数表示类是否需要初始化, Class.forName(className)默认是需要初始化。一旦初始化,就会触发目标对象的 static块代码执行,static参数也也会被再次初始化。 ClassLoader.loadClass(className)方法,内部实际调用的方法是 ClassLoader.loadClass(className,false); 第2个 boolean参数,表示目标对象是否进行链接,false表示不进行链接,由上面介绍可以,不进行链接意味着不进行包括初始化等一些列步骤,那么静态块和静态对象就不会得到执行 -
Mybatis:OR/M (Object-Relation Mapping)
数据库表和java的POJO/DAO类对应关系
//mybatis对java反射进行的一个封装,所有与反射相关的操作,均靠此类执行 public class Reflector{ private final Class<?> type; private final String[] readablePropertyNames; private final String[] writeableProperNames; private final Map<String, Invoker> setMethods = new HashMap<>(); private final Map<String, Invoker> getMethods = new HashMap<>(); private final Map<String, Class<?>> setTypes = new HashMap<>(); private final Map<String, Class<?>> getTypes = new HashMap<>(); private Constructor<?> defaultConstructor; private Map<String, String> caseInsensitivePropertyMap = new HashMap<>(); public Reflector(Class<?> clazz){ type = clazz; addDefaultConstructor(clazz); addGetMethods(clazz); addSetMethods(clazz); addFields(clazz); redablePropertyNames = getMethods.keySet().toArray(new String[0]); writeableProperNames = setMethods.keySet().toArray(new String[0]); } }

浙公网安备 33010602011771号