java的反射机制(菜鸟随笔)
java反射具体实现的功能有3种
1.运行时创建对象
//以String类为例子
CLass cs_Str=Class.forName("java.lang.String");
Stirng str=(String)cs_Str.newInstance();
//提示newInstance()方法已经被弃用 可以用如下方法来替代
String str=(String)cs.getDeclaredConstructor().newInstance();
2.运行时调用对象方法
//反射调用静态类的方法。
Class<Math> csStr=Math.class;
Method method_sin=csStr.getMethod("sin",double.class);
//静态类不实例化
System.out.println("结果:"+ method_sin.invoke(null,1.0));
//反射调用非静态类 调用无参构造函数;
Class<Random> randomClass=Random.class;
Method method_nextInt=randomClass.getMethod("nextInt", int.class);
System.out.println(
"使用无参构造函数:"+
method_nextInt.invoke(randomClass.getDeclaredConstructor().newInstance(),10)
);
//使用带参数的构造函数创建对象并调用方法
Class<Random> randomClass1=Random.class;
Method method_nextInt1=randomClass1.getMethod("nextInt", int.class);
System.out.println(
"使用带参构造函数:"+
method_nextInt1.invoke(randomClass.getDeclaredConstructor(long.class).newInstance(1),10)
);
3.获取一个类的所有成员以及方法
Class cs = Class.forName("java.lang.String");
//获取所有方法成员
Method[] methods= cs.getMethods();
Field[] fields= cs.getDeclaredFields();
//获取简单类名
System.out.println("类名"+cs.getSimpleName());
for(Method method:methods)
{
System.out.println("方法名:"+method.getName());
}
System.out.println("成员变量");
for(Field field:fields)
{
System.out.println("变量类型:"+field.getType()+" 变量名:"+field.getName());
}
getDeclared…获取定义的方法/字段,包含公有和私有 私有的如果想要访问那么需要手动设置访问权限为true
-------------简单测试类
public class MyTest {
private String mimi="秘密";
private void show()
{
System.out.println("我真不想告诉你:"+mimi);
}
}
-------------实验代码
Class<MyTest> myTestClass=MyTest.class;
MyTest myTest=myTestClass.getDeclaredConstructor().newInstance();
//获取私有字段秘密
Field field_mimi=myTestClass.getDeclaredField("mimi");
//设置访问权限为可访问
field_mimi.setAccessible(true);
//打印私有字段:mimi
System.out.println(field_mimi.get(myTest));
//修改私有字段的值
field_mimi.set(myTest,"好了,这已经不是秘密了");
//获取私有方法
Method method=myTestClass.getDeclaredMethod("show");
//设置访问权限
method.setAccessible(true);
//调用私有方法
method.invoke(myTest);
输出结果
秘密
我真不想告诉你:好了,这已经不是秘密了进程完成,退出码 0
4.反射和动态代理
//创建接口
public interface ItestAble {
public void doSomething();
}
//实现接口
public class TestImpl implements ItestAble{
@Override
public void doSomething() {
System.out.println("干了点事");
}
}
//实现InvacationHandler接口
//创建代理对象,使用Proxy类中的静态方法newProxyInstance得到一个动态的代理对象,让代理对象来实现某些事
Class testClass= Class.forName("org.test.jinTest.TestImpl");
TestImpl testImpl=(TestImpl) testClass.getDeclaredConstructor().newInstance();
TestinvocationHandler testinvocationHandler=new TestinvocationHandler(testImpl);
ItestAble itestAble= (ItestAble)Proxy.newProxyInstance(testClass.getClassLoader(),testClass.getInterfaces(),testinvocationHandler);
itestAble.doSomething();
输出结果
做点准备
干了点事
干完收工
看代理时想起来,学java好像没用到过委托,找了找好像java并没有支持委托类型,怀念咦哈。
java中类似的是:将参数设置成接口类型,传入实现类。
java内省
简述:内省(IntroSpector)是Java 语言对 JavaBean 类属性、事件的一种缺省处理方法。(通过反射来操作JavaBean)。
JavaBean简单理解车:成员都是私有通过get();Set()方法来获取和设置。
简单带过:
//通过类名得到相应的BeanInfo对象
BeanInfo info = Introspector.getBeanInfo(类名.class);
//获取成员变量数组
PropertyDescriptor[] propertyDescriptors = info.getPropertyDescriptors();
for(PropertyDescriptor p:propertyDescriptors)
{
p.getReadMethod();//获取get方法;
p.getWriteMethod();//获取set方法
p.getName();//获取变量名
p.getPropertyType();//获取变量类型呢
}