反射学习笔记
(一)Java程序中的各个java类属于同一类事物。描述这类事物的java类名就是Class。每一个Class的实例对象其实就是该对象所属类的字节码。每一个类都有自己的字节码,即使是基本数据类型和void,数组也都有自己的字节码。
(二)反射就是把Java类中的各个成分(构造方法,方法,属性)映射成相应的java类。例如下:
package cn.cx.reflec.study;
import java.lang.reflect.*;
publicclass TestReflection {
publicstaticvoid main(String[] args) throws Exception {
Class<Person> clazz = Person.class;
// Class[] arr = { int.class, String.class };
//反射构造方法
Constructor<Person> c = clazz.getConstructor(int.class, String.class);
Person p = (Person) c.newInstance(6, "xiaohong");
System.out.println(p.say());
//反射属性
Field[] fs = clazz.getDeclaredFields();
for (int i = 0; i < fs.length; i++) {
if (fs[i].getName().equals("age")) {
fs[i].setAccessible(true);
System.out.println(fs[i].getModifiers());
System.out.println(fs[i].getInt(p));
} else {
}
}
//反射方法
Method[] ms = clazz.getMethods();
for(int i=0; i<ms.length; i++) {
if(ms[i].getName().equals("setName")) {
ms[i].invoke(p, "chenxin");
}
//System.out.println(ms[i].getName());
}
System.out.println(p.getName());
}
================Person类=========================
package cn.cx.reflec.study;
publicclass Person {
privateintage;
private String name;
public Person(int age) {
this.age = age;
}
public Person(String name) {
this.name = name;
}
public Person(int age, String name) {
super();
this.age = age;
this.name = name;
}
public String say() {
returnthis.name+this.age;
}
publicint getAge() {
returnage;
}
publicvoid setAge(int age) {
this.age = age;
}
public String getName() {
returnname;
}
publicvoid setName(String name) {
this.name = name;
}
}
(三)替换字符字段的值
package cn.cx.reflec.study;
import java.lang.reflect.*;
publicclass Exercise01 {
publicstaticvoid main(String[] args) throws Exception {
Demo d = new Demo();
Class clazz = Demo.class;
Field[] fs = clazz.getDeclaredFields();
for(int i=0; i<fs.length; i++) {
if(fs[i].getType() == String.class) {
if(fs[i].getModifiers() == Modifier.PRIVATE) {
fs[i].setAccessible(true);
String str = (String)fs[i].get(d);
if(str.contains("a")) {
str = str.replaceAll("a", "b");
fs[i].set(d, str);
//System.out.println(str);
}
} else {
String str = (String)fs[i].get(d);
if(str.contains("a")) {
str = str.replaceAll("a", "b");
fs[i].set(d, str);
//System.out.println(str);
}
}
}
}
for(int i=0; i<fs.length; i++) {
if(!fs[i].isAccessible()) {
fs[i].setAccessible(true);
System.out.println(fs[i].get(d));
} else {
System.out.println(fs[i].get(d));
}
}
}
}
class Demo {
public String str1 = "ball";
private String str2 = "basketball";
private String str3 = "baby";
private String str5 = "back";
private String str4 = "bad";
publicintnum;
privatebooleanflag;
(四)通过Properties文件得到类名来反射(框架的做法)
package cn.cx.reflec.study;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collection;
import java.util.Properties;
publicclass FramTest {
publicstaticvoid main(String[] args) throws Exception{
Properties pro = new Properties();
InputStream in = FramTest.class.getClassLoader().getResourceAsStream("fram.properties");
//FileInputStream fis = new FileInputStream("fram.properties");
pro.load(in);
//fis.close();
String className = pro.getProperty("className");
Collection c = (Collection)Class.forName(className).newInstance();
c.add(1);
c.add(2);
c.add(3);
c.add(4);
System.out.println(c);
}
(五)JavaBean就是特殊的Java类(方法符合特定规则 getXxx() setXxx())。内省Introspector用来操作javabean的api。
package cn.cx.reflec.study;
import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.lang.reflect.*;
import java.util.Properties;
publicclass IntrospectorDemo {
publicstaticvoid main(String[] args) throws Exception {
Person p = new Person(23,"chenxin");
PropertyDescriptor pd = new PropertyDescriptor("name", Person.class);
//获取name属性的get方法
Method rm = pd.getReadMethod();
Object o = rm.invoke(p);
System.out.println(o);
//获取name属性的set方法
Method wm = pd.getWriteMethod();
wm.invoke(p, "laopo");
System.out.println(p.getName());
}
(六)注解Annotation 定义注解用@interface。元注解:注解的注解。RetentionPolicy.SOURCE,RetentionPolicy.CLASS, RetentionPolicy.RUNTIME作用范围分别对应:源文件,class文件,内存字节码。注解可用来代替配置文件,告诉程序(类)如何运行。
(七)自定义注解:
package cn.cx.Anotation.stu;
@Retention(RetentionPolicy.RUNTIME)//声明注解的作用域
public@interfaceMyAnnotation {
//注解的属性可以是如下类型及其他们的一维数组
String name();
String password() default"123";
int age() default 22;
Gender gender() default Gender.FEMALE;
Class clazz() default String.class;
MyAnnotation2 my2();
int[] arr();
}
@interfaceMyAnnotation2 {
String name();
}
===============用的时候如下============
package cn.cx.Anotation.stu;
@MyAnnotation(name="chenxin",arr={1,2,3},my2=@MyAnnotation2(name="myAno2"),gender=Gender.MALE)
publicclass Demo01 {
publicstaticvoid main(String[] args) {
}
}
(八)反射注解:
package cn.cx.Anotation.stu;
@MyAnnotation(name="chenxin",arr={1,2,3},my2=@MyAnnotation2(name="myAno2"),gender=Gender.MALE)
publicclass Demo01 {
publicstaticvoid main(String[] args) {
Class clazz = Demo01.class;
MyAnnotation myAno = (MyAnnotation) clazz.getAnnotation(MyAnnotation.class);
String name = myAno.name();
int age = myAno.age();
//String my2name = myAno.my2().name();
int arr[] = myAno.arr();
System.out.println(name);
System.out.println(age);
//System.out.println(my2name);
System.out.println(arr);
}
}