最近看rpc框架,中间用到了反射,以前也早就听说过反射,用处大大的广。
反射的作用
Java的反射机制、能够在java运行时根据类的路径去获取与路径对应的Class对象。在根据这个类对象去获取类的成员变量、方法、构造这些东西、哪怕他们是私有的。获取到这些东西来做什么?你可以用他们来判断、也可以调用他们去完成某些功能。
反射机制就是专门帮我们做那些重复的有规则的事情。
反射的常用用法:
- 利用打开office软件的demo,不用修改main程序,根据输入动态地调用对应的office,方便扩展。
package office;
public class Office {
public static void main(String[] args) {
Class c = null;
try {
c = Class.forName(args[0]);
} catch (ClassNotFoundException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
OfficeAble office = null;
try {
office = (OfficeAble) c.newInstance();
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
office.start();
}
}
package office;
public interface OfficeAble {
public void start();
}
package office;
public class Excel implements OfficeAble{
@Override
public void start() {
// TODO Auto-generated method stub
System.out.println("Excel...start...");
}
}
package office;
public class Word implements OfficeAble{
@Override
public void start() {
// TODO Auto-generated method stub
System.out.println("Word...start...");
}
}
- 下面是反射的常用用法展示:包括获取类类型的几种方法、利用类类型生成对象、获取方法名字、变量、构造函数、函数返回值、函数调用、以及一个表现反射是发生在运行期的。
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
//打印类中的相关信息,包括方法名、成员变量、构造函数
public class ReflectTest3 {
//获取类类型的几种方法
public void getClassType() {
// one
Class c1 = A.class;
System.out.println(c1);
//second
A a = new A();
Class c2 = a.getClass();
System.out.println(c2);
System.out.println(c1 == c2);
//third
Class c3 = null;
try {
c3 = Class.forName("A");
System.out.println(c3);
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//利用类类型去生成对象
try {
A test = (A) c1.newInstance();
test.print();
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//打印方法信息
public void printMethodMessage(Object object) {
//获取类类型
Class test = object.getClass();
//获取方法名数组,获取返回值、方法名、参数类型
Method[] methods = test.getMethods();
for(int i=0; i<methods.length; ++i) {
Class returnType = methods[i].getReturnType();
System.out.print(returnType.getName()+ ""); //返回值
System.out.print(methods[i].getName()+ "("); //方法名
Class[] paramTypes = methods[i].getParameterTypes();
for(Class class1:paramTypes) {
System.out.print(class1.getName());
}
System.out.println(")");
}
}
//获取类的public的成员变量
public void printFieldMessage(Object object) {
Class c = object.getClass();
Field[] fields = c.getDeclaredFields();
for(Field field: fields) {
Class fieldType = field.getType();
String typeName = fieldType.getName(); //获取类型名
String fieldName = field.getName(); //获取变量名
System.out.println(typeName + " " + fieldName);
}
}
//获取构造函数的信息
public void printConMessage(Object object) {
Class c = object.getClass();
//构造函数也是对象
Constructor[] constructors = c.getDeclaredConstructors();
for(Constructor cs: constructors) {
System.out.print(cs.getName()+"("); //获取构造函数名字
Class[] paramTypes = cs.getParameterTypes();
for(Class paramType:paramTypes) {
System.out.print(paramType.getName()+ " ");
}
System.out.println(")");
}
}
//方法反射
public void methodReflect() {
//获取类类型
A a = new A();
Class c = a.getClass();
//获取方法对象
try {
Method m1 = c.getMethod("print");
m1.invoke(a);
Method m2 = c.getMethod("print", int.class, int.class);
m2.invoke(a, 1, 2);
Method m3 = c.getMethod("print", String.class, String.class);
m3.invoke(a, "hello", "world");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//反射是在运行期的,绕过了编译器
//通过arraylist添加不同类型的数据,来看看这个特性
public void runtimeTest() {
ArrayList<String> test = new ArrayList<String>();
test.add("hello");
//test.add(20); //编译器报错
Class c = test.getClass();
Method m;
try {
m = c.getMethod("add", Object.class);
m.invoke(test, 20);
System.out.println(test.size()); //通过反射,已经将20添加到了ArrayList<String>中,绕过了编译器的语法检查
System.out.println(test);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//test method
public static void main(String[] args) {
ReflectTest3 test = new ReflectTest3();
System.out.println("-------------------分割线--获取类类型的几种方法-------------------");
test.getClassType();
System.out.println("-------------------分割线--打印方法信息-------------------");
String s = "hello";
test.printMethodMessage(s);
System.out.println("-------------------分割线--打印变量名信息-----------------");
test.printFieldMessage(s);
System.out.println("-------------------分割线--打印构造函数信息--------------");
test.printConMessage(s);
System.out.println("-------------------分割线--使用方法反射-----------------");
test.methodReflect();
System.out.println("-------------------分割线--反射是在运行期的-----------------");
test.runtimeTest();
}
}
class A {
public void print() {
System.out.println("hello,world");
}
public void print(int a, int b) {
System.out.println(a+b);
}
public void print(String a, String b) {
System.out.println(a.toUpperCase()+","+b.toLowerCase());
}
}
运行结果:
-------------------分割线--获取类类型的几种方法-------------------
class A
class A
true
class A
hello,world
-------------------分割线--打印方法信息-------------------
booleanequals(java.lang.Object)
java.lang.StringtoString()
inthashCode()
intcompareTo(java.lang.Object)
intcompareTo(java.lang.String)
intindexOf(java.lang.Stringint)
intindexOf(int)
intindexOf(intint)
intindexOf(java.lang.String)
java.lang.StringvalueOf(float)
java.lang.StringvalueOf(double)
java.lang.StringvalueOf(boolean)
java.lang.StringvalueOf([Cintint)
java.lang.StringvalueOf([C)
java.lang.StringvalueOf(java.lang.Object)
java.lang.StringvalueOf(char)
java.lang.StringvalueOf(int)
java.lang.StringvalueOf(long)
charcharAt(int)
intcodePointAt(int)
intcodePointBefore(int)
intcodePointCount(intint)
intcompareToIgnoreCase(java.lang.String)
java.lang.Stringconcat(java.lang.String)
booleancontains(java.lang.CharSequence)
booleancontentEquals(java.lang.StringBuffer)
booleancontentEquals(java.lang.CharSequence)
java.lang.StringcopyValueOf([Cintint)
java.lang.StringcopyValueOf([C)
booleanendsWith(java.lang.String)
booleanequalsIgnoreCase(java.lang.String)
java.lang.Stringformat(java.util.Localejava.lang.String[Ljava.lang.Object;)
java.lang.Stringformat(java.lang.String[Ljava.lang.Object;)
[BgetBytes()
[BgetBytes(java.lang.String)
voidgetBytes(intint[Bint)
[BgetBytes(java.nio.charset.Charset)
voidgetChars(intint[Cint)
java.lang.Stringintern()
booleanisEmpty()
intlastIndexOf(int)
intlastIndexOf(intint)
intlastIndexOf(java.lang.Stringint)
intlastIndexOf(java.lang.String)
intlength()
booleanmatches(java.lang.String)
intoffsetByCodePoints(intint)
booleanregionMatches(intjava.lang.Stringintint)
booleanregionMatches(booleanintjava.lang.Stringintint)
java.lang.Stringreplace(charchar)
java.lang.Stringreplace(java.lang.CharSequencejava.lang.CharSequence)
java.lang.StringreplaceAll(java.lang.Stringjava.lang.String)
java.lang.StringreplaceFirst(java.lang.Stringjava.lang.String)
[Ljava.lang.String;split(java.lang.String)
[Ljava.lang.String;split(java.lang.Stringint)
booleanstartsWith(java.lang.String)
booleanstartsWith(java.lang.Stringint)
java.lang.CharSequencesubSequence(intint)
java.lang.Stringsubstring(intint)
java.lang.Stringsubstring(int)
[CtoCharArray()
java.lang.StringtoLowerCase()
java.lang.StringtoLowerCase(java.util.Locale)
java.lang.StringtoUpperCase(java.util.Locale)
java.lang.StringtoUpperCase()
java.lang.Stringtrim()
voidwait(longint)
voidwait(long)
voidwait()
java.lang.ClassgetClass()
voidnotify()
voidnotifyAll()
-------------------分割线--打印变量名信息-----------------
[C value
int hash
long serialVersionUID
[Ljava.io.ObjectStreamField; serialPersistentFields
java.util.Comparator CASE_INSENSITIVE_ORDER
int HASHING_SEED
int hash32
-------------------分割线--打印构造函数信息--------------
java.lang.String([B )
java.lang.String([B int int )
java.lang.String([B java.nio.charset.Charset )
java.lang.String([B java.lang.String )
java.lang.String([B int int java.nio.charset.Charset )
java.lang.String(int int [C )
java.lang.String([C boolean )
java.lang.String(java.lang.StringBuilder )
java.lang.String(java.lang.StringBuffer )
java.lang.String([I int int )
java.lang.String([C int int )
java.lang.String([C )
java.lang.String(java.lang.String )
java.lang.String()
java.lang.String([B int int java.lang.String )
java.lang.String([B int )
java.lang.String([B int int int )
-------------------分割线--使用方法反射-----------------
hello,world
3
HELLO,world
-------------------分割线--反射是在运行期的-----------------
2
[hello, 20]
反射的应用
工厂方法、代理+代理=动态代理(应用在spring的AOP上)、ibatis等
下面是我用maven+java反射+注解+jdbc写的一个简单的orm,代码放在github:https://github.com/zy416548283/JDBCSimpleORM
反射优缺点
优点:按名称动态检索信息,让运行中的程序操作这些信息,无需提前硬编码目标类。
缺点:性能问题.
反射原理
待分析
版权声明:本文为博主原创文章,未经博主允许不得转载。
时间: 2024-10-22 03:33:39