概述
动态获取的数据以及动态调用对象的方法的功能被称为java的反射
通过反射,可以获取JAVA的Class类对象(类,接口,枚举)的信息,可以动态创建对象,可以调用类型中的方法,属性,构造函数
演示案例
//1,获取类的类对象
Class clazz = Student.class;
//2,可以获取student类的名称
String clazzName = clazz.getName();
System.out.println("类的名称:"+clazzName);
//3,获取student类的所有的属性
Field[] fields= clazz.getDeclaredFields();
for (Field field : fields) {
System.out.println("属性名称:"+field.getName());
}
//4,获取student类的所有的方法
Method[] methods = clazz.getDeclaredMethods();
for (Method m : methods) {
System.out.println("方法名称:"+m.getName());
}
类对象
概念:
类的对象:基于某个类new出来的对象,也称为实例对象
类对象:类加载的产物,封装了一个类的所有信息(类名,父类,接口,属性,方法,构造方法)
每个类加载到内存都会生成一个唯一的类对象
类对象的获取:
获得对象Class有四种方式
Class.forName(包名.类名)
类名,class
对象名.getClass()
类加载器.ClassLoader
演示案例
//第1种方式: 让jvm去加载Person类, 自动调用静态块
//Class c = Class.forName("com.xyao.test.Person");
//实例化(自动调用构造函数)
//c.newInstance();
//第2种方式: 类名.class
//Class c = Person.class;
//c.newInstance(); //才去加载
//第3种方式: 对象名.getClass
//Person p = new Person();
//Class c = p.getClass();
//第4种方式: 类加载器
//类加载器
ClassLoader load = ClassLoader.getSystemClassLoader();
//加载Person这个类
Class c = load.loadClass("com.xyao.test.Person");
c.newInstance(); //实例化对象
类对象的常用方法:
public String getName() 获取类的完全名称
public Package getPackage() 获取包的信息
public Class<? super T>getSuperclass() 获取父类
public Class<?>[] getInterfaces() 获取实现父类接口
public Field[] getField() 获取字段信息
public Method[] getMethod 获取方法信息
public Constructor<?>[]getConstructor 获取构造方法
public T newInstance() 反射创建对象
反射通过操作:使用反射机制获取类对象,并使用Class对象的方法获取表示类成员的各种对象(比如Constructor,Method,Field等),实现反射各种应用
属性对象:
属性对象的基本方法:
获得单个的公有属性getField(属性名字)
获得属性(与修饰符无关)getDeclaredField(属性名字)
获得本类(父类)所有的公有属性:getFields()
获得本类所有的属性(与修饰符无关):getDeclaredFields()
获得属性名:getName
获得属性类型:getType()
给属性赋值:set(对象,属性值)
给属性取值:get(对象)
案例演示
//得到Person的类对象
Class c = Class.forName("com.xyao.test.Person");
//实例化
Person p = (Person)c.newInstance();
/*************************************/
System.out.println("得到单个公有属性---");
Field f1 = c.getField("name");
//为属性赋值
//f1.set("本属性所在类的对象","属性值");
f1.set(p, "小f");
//取属性值
System.out.println(f1.get(p));
/*************************************/
System.out.println("得到所有的公有属性----");
Field[] fields = c.getFields();
for (Field f : fields) {
System.out.println(f.getName()); //属性名字
}
/*************************************/
System.out.println("得到单个私(非公)有属性---");
//Declared声明
Field f2 = c.getDeclaredField("age");
//单个解锁
f2.setAccessible(true);
//赋值
f2.set(p, 10);
System.out.println(f2.get(p)); //取值
/*************************************/
System.out.println("得到所有声明的属性(公,私...)----");
Field[] fs = c.getDeclaredFields();
//多个解锁
Field.setAccessible(fs,true);
for (Field f : fs) {
//得到属性名字
String name = f.getName();
//得到访问修饰符
int modi = f.getModifiers(); //数字
//将数字转换成String类型
String mod = Modifier.toString(modi);
//得到类型的名字
String type = f.getType().getName();
System.out.println(mod+" " + type + " " + name);
}
方法对象
方法对象的基本方法
获得当个的公有方法getMethod(方法名字,参数列表)
获得本类(父类)所有的公有方法:getMethods()
获得方法(与修饰符无关)getDeclaredMethod(方法名字,参数列表)
获得本类所有的方法(与修饰符无关)getDeclaredMethods()
方法名:getName
方法访问修饰符:getModifiers()
方法的返回类型:getReturnType().getName
方法的参数列表:getParameterTypes()
调用方法:invoke(对象,方法的参数列表)
代码演示
//得到无参的方法
Method m1 = c.getMethod("a", null);
//调用无参方法
m1.invoke(p , null);
System.out.println("调用单个参数的公有方法-------");
Method m2 = c.getMethod("a2", String.class);
//调用带一个String类型的参数的方法
m2.invoke(p, "小S");
System.out.println("调用多个参数的公有方法-------");
Method m3 = c.getMethod("a3", String.class, Integer.TYPE);
//调用带一个String类型的参数的方法
//m3.invoke(p, "小S",10);
m3.invoke(p, new Object[]{"小S",10});
System.out.println("得到自己和父类的所有的公有方法--------");
Method[] ms = c.getMethods();
for (Method m : ms) {
//得到本类和Object类中的所有公有方法
System.out.println(m.getName());
-------------------"获得一个私有的方法---------------------
Method m4 = c.getDeclaredMethod("a4", null);
//解锁
m4.setAccessible(true);
//调用私有方法
m4.invoke(p, null);
System.out.println("得到本类中所有的方法(私有,公有...)
Method[] ms2 = c.getDeclaredMethods();
for (Method m : ms2) {
System.out.println(m.getName()); //方法的名字
System.out.println(getModif(m.getModifiers()));
//得到具体的修饰符
public static String getModif(int mod){
return Modifier.toString(mod);}
}
构造方法对象:
构造方法对象的基本方法
获得单个公有构造函数getConstructor(参数列表)
获得单个的构造函数(与修饰符无关)getDeclaredConstructor(参数列表)
获得本类所有的公有构造函数:getConstructors()
获得本类所有的构造函数(与修饰符无关):getDeclaredConstructor
调用构造函数:
无参构造函数:newlnstance()
有参构造函数:newlnstance(参数列表)
案例演示
//获得公有无参构造
Constructor c1 = c.getConstructor(null);
c1.newInstance();
//获得公有String类型有参构造
Constructor c2 = c.getConstructor(String.class);
c2.newInstance("sss");
//得到本类所有的公有构造函数
Constructor[] cs = c.getConstructors();
//获得所有公有构造
//c.getConstructors()
//获得所有声明的构造函数(公,私...)
//c.getDeclaredConstructors();
注解编程:
定义:
注解(Annotation),也叫元数据.一种代码级别的说明.它是JDK1.5及以后版本引入的一个特性,与类,接口,枚举是在同一个层次.他可以在声明在包,类,字段,方法,局部变量,方法参数等的前面,用来对这些元素进行说明,注释
作用分类
编写文档:通过里表示的元数据生成文档
代码分析:通过代码里面的标识的元数据对代码进行分析[反射的使用补充]
编译检查:通过代码里表示的元数据让编译器能实现基本的编译检查
定义注解:
定义注解使用@interface关键字,注解中只能包含属性
public @interface MyAnnotation {
//属性(类似方法)
String name() default "张三";
int age() default 20;
}
元注解
1,元注解的作用就是负责注解其他注解。Java5.0定义了4个标准的meta-annotation类型,它们被用来提供对其它 annotation类型作说明。Java5.0定义的元注解:
1.@Target,
2.@Retention,
.@Documented,
4.@Inherited
2,这些类型和它们所支持的类在java.lang.annotation包中可以找到。下面我们看一下每个元注解的作用和相应分参数的使用说明。