反射基础
概念
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
要想解剖一个类,必须先要获取到该类的字节码文件对象。而解剖使用的就是Class类中的方法.所以先要获取到每一个字节码文件对应的Class类型的对象.
Study注解定义
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE,ElementType.FIELD,ElementType.METHOD})
public @interface Study {
String name() default "hallo world!";
String[] morse();
}
User类
@Study(name="这是个类注解",morse={"1","2"})
public class User {
@Study(name="这是个类注解",morse={"3","4"})
private String name;
private int age;
public String getName() {
return name;
}
public int getAge() {
return age;
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
@Study(name="这是个方法注解",morse={"5","6"})
public int addAge(int i){
this.age+=i;
return this.age;
}
}
- 获取类对象
// 1.反射获取类
User user=new User();
Class<?> c1= user.getClass();
Class c2=Class.forName("com.neteasy.reflact.User");
System.out.println("1 :"+c1);
System.out.println("2 :"+c2);
System.out.println("3 :"+User.class);
1 :class com.neteasy.reflact.User
2 :class com.neteasy.reflact.User
3 :class com.neteasy.reflact.User
可以看出,以上方法获取到的是同一个类对象。
- 获取类名
//2. 反射获取类name
String c1name=c1.getName();
String c1SimpName=c1.getSimpleName();
System.out.println("3 :"+c1name);
System.out.println("4 :"+c1SimpName);
3 :com.neteasy.reflact.User
4 :User
一个全类名和类名。
- 反射获取类属性
Field[] fieds=c1.getDeclaredFields();
user.setAge(26);
user.setName("司马懿");
for(Field field:fieds) {
System.out .println(field); //这样是属性的类路径
System.out .println(field.getName());//获取属性名
field.setAccessible(true);
if ("name".equals(field.getName())) {
String name = (String) field.get(user);
System.out.println("5 :" + name);
} else {
int age = (int) field.get(user);
System.out.println("6 :" + age);
}
}
private java.lang.String com.neteasy.reflact.User.name
name
5 :司马懿
private int com.neteasy.reflact.User.age
age
6 :26
获取某具体对象的属性值。 其中需要注意的是为了防止类对象中的private属性在其他类中调用报错,我们需要field.setAccessible(true);将该属性设为可访问。
- 为指定实例对象赋值
// 4 为指定实例对象赋值
User u= (User) c1.newInstance();
for(Field field:fieds) {
field.setAccessible(true);
if ("name".equals(field.getName())) {
field.set(u,"诸葛亮");
}else{
field.set(u,18);
}
System.out.println(field.get(u));
}
诸葛亮
18
- 反射获取方法并且执行
//5 反射获取方法并执行
Method[] m=c1.getMethods();
for(Method m1:m){
if(!("setName".equals(m1.getName()))){
continue;
}
m1.invoke(u,"关云长");
System.out.println(u.getName());
}
Method addm=c1.getDeclaredMethod("addAge", int.class);
addm.invoke(u,2);
System.out.println("7 :"+u.getAge());
关云长
7 :20
在获取方法时,可以通过getMethods()
获取类中所有方法进行遍历,获取到自己想要的方法。也可以通过c1.getDeclaredMethod()
根据方法名和参数类型获取到自己想要的方法。
- 获取 类,属性,方法上的注解信息
// 反射获取类的注解信息
Study a =c1.getAnnotation(com.neteasy.reflact.Study.class);
System.out.println("8 :"+((Study) a).name());
String[] str=a.morse();
for(String s:str){
System.out.println("9 :"+s);
}
// 反射获取属性的注解信息
for (Field fied : fieds) {
Study annotation = fied.getAnnotation(Study.class);
if(annotation==null){
continue;
}
String name = annotation.name();
System.out.println("10 :"+name);
String[] morse = annotation.morse();
for (String s : morse) {
System.out.println("11 :"+s);
}
}
// 反射获取方法的注解信息
for(Method m1:m){
Study annotation = m1.getAnnotation(Study.class);
if (annotation ==null) {
continue;
}
String name = annotation.name();
System.out.println("12 :"+name);
String[] morse = annotation.morse();
for (String s : morse) {
System.out.println("13 :"+s);
}
}
}
8 :这是个类注解
9 :1
9 :2
10 :这是个类注解
11 :3
11 :4
12 :这是个方法注解
13 :5
13 :6
这样就可以通过反射获取类中的所有想知道的信息。
通过反射生成sql语句
Table注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Table {
String name();
}
Column注解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Column {
String name() default "";
}
Order类
@Table(name="t_order")
public class Order {
@Column
private String id;
@Column(name="order_id")
private String orderId;
@Column(name="user_name")
private String userName;
@Column(name="user_id")
private String userId;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getOrderId() {
return orderId;
}
public void setOrderId(String orderId) {
this.orderId = orderId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
}
SqlUtil类
public class SqlUtil {
public static StringBuffer getSql(Object obj) throws IllegalAccessException {
Class clz=obj.getClass();
StringBuffer sb1=new StringBuffer();
StringBuffer sb2=new StringBuffer();
sb1.append("select ");
sb2.append("where ");
Field[] declaredFields = clz.getDeclaredFields();
for (Field declaredField : declaredFields) {
Column annotation = declaredField.getAnnotation(Column.class);
declaredField.setAccessible(true);
String column = annotation.name();
String o = (String) declaredField.get(obj);
if("".equals(column)){
sb1.append(" "+declaredField.getName()+" ,");
if(o!=null){
sb2.append("and"+declaredField.getName()+"="+o+" ");
}}else{
sb1.append(" "+column+" , ");
if(o!=null){
sb2.append("and"+column+"="+o+" ");
}
}
}
Table table= (Table) clz.getAnnotation(Table.class);
if(table == null){
throw new RuntimeException("缺少表名!!");
}
sb1.append(" from "+table.name());
sb1=sb1.append(" "+sb2);
return sb1;
}
}
main
public static void main(String[] args) {
Order order=new Order();
order.setUserId("1999");
StringBuffer sb=new StringBuffer();
try {
sb=SqlUtil.getSql(order);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
System.out.println(sb);
}
运行结果
select id , order_id , user_name , user_id , from t_order where anduser_id=1999
顺利完成!