反射
JAVA-准动态语言
JAVA和C、C++一样是静态语言,运行时不能像Python,js一样改变程序的结构
如js中的eval("var x = 1")
或python中的
def square(x);square = lambda x : x*x
但是JAVA可以通过反射机制获得类似动态语言的特性
java的反射机制允许通过调用反射API,在程序运行期间,获取类的任何内部信息,直接操作对象的任意内部属性和方法
通过获取类的Class对象
通过反射可以获取类的Class对象,从而获取类的信息(变量、方法等)
方法一
可以通过类名获取类在内存中的class对象
Class c = Class.forName();
方法二
可以通过Object的getClass方法获得一个对象对应的类的Class对象
Class c1 = new student(2,"wm").getClass();
方法三
可以通过类名.class来获取类的Class对象
Class c2 = student.class;
获取父类Class对象
通过本类的Class对象获取父类的Class对象
Class c3 = c.getSuperclass;
public class testForName {
public static void main(String args[]) throws ClassNotFoundException, NoSuchMethodException {
Class c = Class.forName("student");
Class c1 = new student(2,"wm").getClass();
Class c2 = student.class;
//c,c1,c2指向同一个Class对象
System.out.println(c2.getMethod("getName"));
Class c3 = c.getSuperclass();
System.out.println(c3.getMethod("getJob"));
}
}
class person{
private String job = "工人";
public String getJob() {
return job;
}
public void setJob(String job) {
this.job = job;
}
}
class student extends person{
private int id = 0;
private String name = "mak";
public int getId() {
return id;
}
public String getName() {
return name;
}
public student(int id, String name) {
this.id = id;
this.name = name;
}
public void setId(int id) {
this.id = id;
}
@Override
public String toString() {
return "student{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
获取类的信息
获取类名:c.getName()
获取本类及其父类的方法:c.getMethod("getId")
获取类的public变量:Field[] Fields = c.getFields()
获取类的所有变量:Field[] Fields = c.getDeclaredFields()
Field id = c.getDeclaredFields("id")
等等,用的时候跟进去看一下就行
动态操作反射创建的对象
可以通过获得的Class对象去修改属性、执行方法等
以这个student类为例:
class student {
private int id = 0;
private String name = "mak";
public int getId() {
return id;
}
public String getName() {
return name;
}
public student(int id, String name) {
this.id = id;
this.name = name;
}
public void setName(String name) {
this.name = name;
}
public void setId(int id) {
this.id = id;
}
void test(String name){
System.out.println("hello,"+this.name+" and "+name);
}
@Override
public String toString() {
return "student{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
通过反射创建对象
Class stuclass = Class.forName("student");
student stu = (student)stuclass.newInstance();
通过反射创建有带参构造器的对象
Constructor constr = stuclass.getConstructor(int.class,String.class); //获取类的构造器,参数:构造器参数类型的class
student stu1 = (student) constr.newInstance(12,"Tom");
执行对象的方法
Method stname = stuclass.getMethod("setName", String.class); //获取类的方法,参数:方法名,方法参数类型的Class
stname.invoke(stu1,"wm"); //invoke(激活):执行函数,参数:(用于执行函数的对象,函数参数)
Method hello = stuclass.getDeclaredMethod("test", String.class);
hello.invoke(stu1,"abc");
操作对象属性
Field stuid = stuclass.getDeclaredField("name");
stuid.setAccessible(true); //对于修改private属性,要先关闭程序安全检测(默认为true)
stuid.set(stu1,"wm1111"); //set修改,参数:要修改属性的对象,修改后的值
hello.invoke(stu1,"def");
反射获取泛型
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;
class test11{
//参数是泛型
public void test01(Map<String,Integer> map, List<student> list){
System.out.println("test01");
}
//返回值是泛型
public Map<String,Integer> test02(){
System.out.println("test02");
return null;
}
}
public class test1 {
public static void main(String args[]) throws NoSuchMethodException {
//获取泛型参数的类:
Method mtd = test11.class.getMethod("test01", Map.class,List.class);
Type[] gnpt = mtd.getGenericParameterTypes(); //获取参数泛型
for (Type gt:gnpt){
System.out.println("#"+gt);
if(gt instanceof ParameterizedType){
Type[] atas = ((ParameterizedType) gt).getActualTypeArguments(); //获得真实参数类
for(Type ata : atas){
System.out.println(ata);
}
}
}
//获取泛型返回值的类:
Method mtd1 = test11.class.getMethod("test01", Map.class,List.class);
Type gt = mtd.getGenericReturnType(); //获取返回值泛型
System.out.println("#"+gt);
if(gt instanceof ParameterizedType){
Type[] atas1 = ((ParameterizedType) gt).getActualTypeArguments(); //获得真实参数类
for(Type ata : atas1){
System.out.println(ata);
}
}
}
}
反射获取注解
import java.lang.annotation.*;
import java.lang.reflect.AnnotatedArrayType;
import java.lang.reflect.Field;
public class testGetAnno {
public static void main(String args[]) throws ClassNotFoundException, NoSuchFieldException {
//获取类的注解
Class cl1 = Class.forName("stus");
Annotation[] annos = cl1.getAnnotations(); //获得注解
for(Annotation anno : annos){
System.out.println("类的注解:"+anno);
}
//获取注解的value值
stuTable stutanno = (stuTable) cl1.getAnnotation(stuTable.class); //获取指定注解类的注解
String value = stutanno.value();
System.out.println("注解的value:"+value);
//获取类的指定属性指定的注解
Field f = cl1.getDeclaredField("name");
stuField stutanno1 = f.getAnnotation(stuField.class);
System.out.println("属性Name的注解中,columnName的值是:"+stutanno1.columnName());
}
}
@stuTable(value = "高三十班")
class stus{
@stuField(columnName = "clm_id",Type = "int",length = 10)
private int id;
@stuField(columnName = "clm_id",Type = "int",length = 2)
private int age;
@stuField(columnName = "clm_id",Type = "varchar",length = 10)
private String name;
public stus(int id, int age, String name) {
this.id = id;
this.age = age;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
//类名注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface stuTable{
String value();
}
//属性注解
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface stuField{
String columnName();
String Type();
int length();
}
Comments NOTHING