二、创建类对象并获取类的完整结构:
package com.atguigu.fanshe;
import org.junit.Test;
public class TestConstructor {
@Test
public void test1() throws Exception {
String className="com.atguigu.fanshe.Person";
Class clazz1=Class.forName(className);//加载一下
//创建对应运行时类的对象
//(newInstance调用的就是类的空参构造器)
//要想能够创建成功:①、要求对应的运行时类要有空参的构造器。②、构造器的权限修饰符的权限要足够
Object obj=clazz1.newInstance();//newInstance默认的返回值类型位Object类型
Person p=(Person)obj;
System.out.println(p);
}
}
1、Field类(获取运行时类的属性):
(1)、getFields():只能获取到运行时类及其父类中声明的public类型的属性的数组形式。
Class clazz1=Person.class;
Field[] field1=clazz1.getFields();
for(int i=0;i<field1.length;i++) {
System.out.println(field1[i]);
}
System.out.println("*****");
(2)、getDeclaredFields():获取运行时类本身声明的所有的属性。
Field[] field2=clazz1.getDeclaredFields();
for(Field f:field2) {
System.out.println(f.getName());
}
(3)、权限修饰符 变量类型 变量名;获取属性各个部分的内容
@Test
public void testField2() {
Class clazz=Person.class;
Field[] field1=clazz.getDeclaredFields();
for(Field f:field1) {
//1、获取每个属性的权限修饰符
int i=f.getModifiers();
String str1=Modifier.toString(i);
System.out.print(str1+" ");
//2、获取属性的变量类型
Class type=f.getType();
System.out.print(type.getName()+" ");
//3、获取属性名
System.out.print(f.getName()+" ");
System.out.println();
}
}
2、Method类(获取运行时类的方法):
package com.atguigu.fanshe;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import org.junit.Test;
public class TestMethod {
@Test
public void test1() {
Class clazz=Person.class;
//1、getMethods():获取运行时类及其父类中所有的声明为public的方法
Method[] m1=clazz.getMethods();
for(Method m:m1) {
System.out.println(m);
}
//2、getDeclaredMethods():获取运行时类本身声明的所有方法
Method[] m2=clazz.getDeclaredMethods();
for(Method m:m2) {
System.out.println(m);
}
}
//注解 权限修饰符 返回值类型 方法名 形参列表 异常
@Test
public void test2() {
Class clazz=Person.class;
Method[] m2=clazz.getDeclaredMethods();
for(Method m:m2) {
//1、注解:
Annotation[] ann=m.getAnnotations();
for(Annotation a:ann) {
System.out.println(a);
}
//2、权限修饰符
String str=Modifier.toString(m.getModifiers());
System.out.println(str+" ");
//3、返回值类型
Class returnType=m.getReturnType();
System.out.println(returnType.getName()+" ");
//4、方法名
System.out.println(m.getName());
//5、形参列表
//6、异常类型
}
}
}
3、Constructor类(获取运行时类的方法):
4、其他类:
package com.atguigu.fanshe;
import java.lang.annotation.Annotation;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import org.junit.Test;
public class TestOther {
//6、获取注解
@Test
public void test6() {
Class clazz=Person.class;
Annotation[] anns=clazz.getAnnotations();
for(Annotation a:anns) {
System.out.println(a);
}
}
//5、获取所在的包
@Test
public void test5() {
Class clazz=Person.class;
Package pack=clazz.getPackage();
System.out.println(pack);
}
//4、获取实现的接口
@Test
public void test4() {
Class clazz=Person.class;
Class[] interfaces=clazz.getInterfaces();
for(Class i:interfaces) {
System.out.println(i);
}
}
//*非常重要**3、获取父类的泛型
@Test
public void test3() {
Class clazz=Person.class;
Type type1=clazz.getGenericSuperclass();
ParameterizedType param=(ParameterizedType)type1;
Type[] ars=param.getActualTypeArguments();
System.out.println(((Class)ars[0]).getName());
}
//2、获取带泛型的父类
@Test
public void test2() {
Class clazz=Person.class;
Type type1=clazz.getGenericSuperclass();
System.out.println(type1);
}
//1、获取运行时的父类
@Test
public void test1(){
Class clazz=Person.class;
Class superClass=clazz.getSuperclass();
System.out.println(superClass);
}
}
三、通过反射调用类中的指定方法、指定属性:
1、调用类中指定的属性:
@Test
public void test3() throws Exception {
Class clazz=Person.class;
//1、获取指定的属性
//getField(String name):获取运行时类中声明为public的指定属性名为name的属性
Field name=clazz.getField("name");
//2、创建运行时类的对象
Person p=(Person)clazz.newInstance();
System.out.println(p);
//3、将运行时类的指定属性赋值
name.set(p,"Jerry");
System.out.println(p);
System.out.println();
//getDeclaredField(String name):获取运行时类中指定的名为name的属性
Field age=clazz.getDeclaredField("age");
//由于属性权限修饰符的限制,为了保证可以给属性赋值,需要在操作前使得此属性可被操作。
// age.setAccessible(true); //如果属性是私有的需要加此语句
age.set(p, 23);
System.out.println(p);
}
2、调用类中指定的方法:
getMethod(String methodName,Class … params):获取运行时类中声明为public的指定的方法。
invoke():调用指定的方法。
3、调用类中指定的构造器:
四、反射的应用之动态代理:
1、静态代理类的编写规则:
package dongtaidaili;
//静态代理
//1、接口
interface ClothFactory{
void productCloth();
}
//2、被代理类
class NickClothFactory implements ClothFactory{
@Override
public void productCloth() {
// TODO Auto-generated method stub
System.out.println("Nick工厂生产一批衣服");
}
}
//3、代理类
class ProxyFactory implements ClothFactory{
ClothFactory cf;
//创建代理类的对象时,实际传入一个被代理类的对象
public ProxyFactory(ClothFactory cf) {
this.cf=cf;
}
@Override
public void productCloth() {
// TODO Auto-generated method stub
System.out.println("代理类开始执行,收代理费¥1000");
cf.productCloth();
}
}
public class TestClothProduce {
public static void main(String[] args) {
NickClothFactory nick=new NickClothFactory();//创建被代理类的对象
ProxyFactory proxy=new ProxyFactory(nick);//创建代理类的对象
proxy.productCloth();
}
}
//一个接口对应一个被代理类和一个代理类。杂。
2、静态代理类的编写规则:
package dongtaidaili;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
//动态代理类的使用
interface Subject {
void action();
}
//被代理类
class RealSubject implements Subject {
public void action() {
System.out.println("我是代理类,记得要执行我i偶!");
}
}
//凡是与动态代理相关的,都要实现InvocationHandler接口。
class MyInvocationHandler implements InvocationHandler {
Object obj;// 实现了接口的被代理类的对象的声明,相当于RealSubject的对象。
// ①、给被代理类的对象实例化;②、返回一个代理类的对象
public Object blind(Object obj) {
this.obj = obj;
// Proxy.newProxyInstance(arg0, arg1, arg2)//;;return语句真正的相当于返回了一个代理类的对象
return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), this);
}
//当通过代理类的对象发起对被重写的方法的调用时,都会转换为对如下的invoke方法的调用
@Override // 调用invoke()方法时,实际调用的是action()方法。
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object returnVal=method.invoke(obj, args);
return returnVal;
}
}
public class TestProxy {
public static void main(String[] args) {
//1、被代理类的对象
RealSubject real=new RealSubject();
//2、创建一个实现了InvocationHandler接口的类的对象
MyInvocationHandler handler=new MyInvocationHandler();
//3、调用blind()方法,动态的返回一个同样实现了real所在类实现的接口Subject的代理类的对象
Object obj=handler.blind(real);
Subject sub=(Subject)obj;//此时sub就是代理类的对象
sub.action();//转到对InvocationHandler接口的实现类的invoke()方法的调用
//再举一例
NickClothFactory nick=new NickClothFactory();
ClothFactory proxyCloth=(ClothFactory)handler.blind(nick);//proxyCloth即为代理类的对象。
proxyCloth.productCloth();
}
}