Java反射机制

1.反射机制是什么

         反射机制是在运行状态中,对于任何一个类,都能知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取信息以及动态调用对象的方法的功能叫做java的反射机制

2.反射机制能做什么

  • 在运行时判断任意一个对象所属的类;
  • 在运行时判断任意一个类所具有的成员变量和方法;
  • 在运行时构造任意一个类的对象;
  • 在运行时调用任意一个对象的方法;
  • 生成动态代理

3.反射机制的相关API

  1.  通过一个对象获得完整的包名和类名

           

Test  test=new Test();
System.out.println(test.getClass().getName);

        2.实例化Class类对象

Class<?> class1=null;
Class<?> class1=null;
Class<?> class1=null;
//一般采用这种形式
class1=Class.forName("com.lj.Test");
class2=Test().getClass();
class3=Test.class;
System.out.println(“类名称”+class1.getName);
System.out.println(“类名称”+class2.getName);
System.out.println(“类名称”+class3.getName);

        3.获取一个对象的父类与实现的接口

Class<?> clazz=Class.forName("com.lj.Test");
//取得父类
Class<?> parentClass=clazz.getSuperclass();
System.out.println("clazz的父类为:"+parentClass.getName);
//clazz的父类为:java.lang.object
//获取所有实现的接口
Class<?> intes[]=clazz.getInterfaces();
System.out.println("clazz实现的接口有:");
for(int i=0;i<intes.length;i++){
System.out.println((i+1)+":"+intes[i]。getName());
}

  4.获取某个类的全部构造函数,通过反射机制实例化一个类的对象

       

Class<?> class1=null;
class1=Class.forName(com.lj.user);
//第一种方式,实例化默认构造方法,调用set赋值
User user=(User)class1.newInstance();
user.setName("jeck");
user.setAge(20);
System.out.println(user);
//第二种方式,取得全部的构造函数,使用构造函数赋值
Constructor<?> cons[]= class1.getConstructor();
//查看每个构造方法需要的参数
for(int i=0;i<cons.length;i++){
 Class<?> clazzs[]=cons[i].getParameterTypes();
 System.out.printl("cons["+i+"](");
 for(int j=0;j<clazzs.length;j++){
  if(j==clazzs.length-1)
     System.out.println(clazzs[j].getName);
else
    System.out.println(clazzs[j].getName()+",");
}
System.out.println(")")
}
//根据获得的结果选择构造函数实例化类的对象
//cons[0](java.lang.String)
//cons[1](int,java.lang.String)
//cons[2]()
user =(User)cons[0].getInstance("jeck");
System.out.println(user);
user =(User)cons[1].getInstance(20,"jeck");
System.out.println(user);

  5.获取某个类的全部属性

Class<?> clazz=Class.forName("com.lj.Test");
System.out.println("---------本类属性---------");
//取得本类的全部属性
Field[] field=clazz.getDeclaredFields();
for(int i=0;i<filed.length;i++){
 //权限修饰符
     int mo=field[i].getModifiers();
     String priv=Modifier.toString(mo);
//属性类型
    Class<?> type=field[i].getType();
    System.out.println(priv+""+type.getName()+"")+field[i].getName()+";");
}

System.out.println("--------实现的接口或者父类的属性---------")
//取得实现的接口或者父类的属性
Field[] field1=clazz.getFileds();
for(int j=0;j<field1.length;j++){
 //权限修饰符
 int mo=field[j].getModifiers();
String priv=Modifier.toString(mo);
//属性类型
    Class<?> type=field[i].getType();
    System.out.println(priv+""+type.getName()+"")+field[j].getName()+";");
}

  6.获取某个类的全部方法

Class<?> clazz=Class.forName("com.lj.Test");
Method method[]=clazz.getMethods();//获取类的全部方法
for(int i=0;i,method.length;i++){
  Class<?>  returnType=method[i].getReturnType();//取得方法的返回类型
 Class<?>   para[]=method[i].getParameterTypes();
  int temp=method[i].getModifiers();//权限修饰符
 System.out.print(Modifier.toString(temp)+"");
 System.out.print(returnType.getName+"");
 System.out.print(method[i].getName+""); 
System.out.print("(")
for(int j=0;i,para.length;j++){
 System.out.println(para[j].getName()+""+"arg"+j);
if(j<para.length-1){
System.out.println(",");
}
Class<?> exce[]=method[i].getExceptionType[];
if(exce.length>0){
System.out.println(")throws");
for(int k=0;k<exce.length;i++){
System.out.print(exce[k].getName()+"");
if(k<length-1){
System.out.print(",");
}
}
}else{
System.out.print(")");
}
System.out.println(); } }

  7.通过反射机制调用每个类的方法

  

Class<?> clazz=Class.forName(com.lj.Test);
//调用Test类中的test1方法
Method method=clazz.getMethod("test1");
method.invoke(clazz.newInstance);

//调用Test类的test2方法
method=clazz.getMethod("test2",int.class,String.class);
method.invoke(clazz.newInstance(),20,"jeck");

public void test1(){
  System.out.println("java反射机制调用某个类的方法一");
}

public void test2(int age,String name){
  System.out.println("java反射机制调用某个类的方法二");
System.out.println("age->"+age+".name->"+name);
}

  8.通过反射机制操作某个类的属性

         

package com.lj;
import java.lang.reflect.field;
public class Test{
  private String proprety=null;
   public static void main(String[] args)throws Exception{
      Class<?> clazz=Class.forName("com.lj.Test");
      Object obj=clazz.newInstance();
   //可以直接对private的属性赋值
 Field field=clazz.getDeclaredField("proprety");
 field.setAccessible(true);
field.set(obj,"java反射机制");
System.out.println(field.get(obj));
}
}

  9.反射机制的动态代理

          

// 获取类加载器的方法
TestReflect testReflect = new TestReflect();
        System.out.println("类加载器  " + testReflect.getClass().getClassLoader().getClass().getName());
package net.xsoftlab.baike;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
//定义项目接口
interface Subject {
    public String say(String name, int age);
}
// 定义真实项目
class RealSubject implements Subject {
    public String say(String name, int age) {
        return name + "  " + age;
    }
}
class MyInvocationHandler implements InvocationHandler {
    private Object obj = null;
    public Object bind(Object obj) {
        this.obj = obj;
        return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), this);
    }
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object temp = method.invoke(this.obj, args);
        return temp;
    }
}
/**
 * 在java中有三种类类加载器。
 * 
 * 1)Bootstrap ClassLoader 此加载器采用c++编写,一般开发中很少见。
 * 
 * 2)Extension ClassLoader 用来进行扩展类的加载,一般对应的是jrelibext目录中的类
 * 
 * 3)AppClassLoader 加载classpath指定的类,是最常用的加载器。同时也是java中默认的加载器。
 * 
 * 如果想要完成动态代理,首先需要定义一个InvocationHandler接口的子类,已完成代理的具体操作。


public class TestReflect {
    public static void main(String[] args) throws Exception {
        MyInvocationHandler demo = new MyInvocationHandler();
        Subject sub = (Subject) demo.bind(new RealSubject());
        String info = sub.say("Rollen", 20);
        System.out.println(info);
    }
}

  

4.反射机制的应用实例

     1.在泛型为Interger的ArrayList中存放一个String类型的对象

 

ArrayList<Interger> list=new ArrayList<Interger>();
Method method=list.getClass().getMethod("add",Object.class);
method.invoke(list,"java反射机制的实例。");
System.out.println(list.get(0));

 2.通过反射取得并修改数组的信息

int [] temp={1,2,3,4,5};
Class<?> demo=temp.getClass().getComponentType();
System.out.println("数组类型:"+demo.getName);
System.out.println("数组长度:"+Array.getLength(temp));
System.out.println("数组的第一个元素:"+Array.get(temp,0));
Array.set(temp,0,100);
System.out.println("修改之后的数组的第一个元素为:"+Array.get(temp,0));

 3.通过反射机制修改数组的大小

int[] temp={1,2,3,4,5,6,7,8,9};
int[] newTemp=(int[])arrayInc(temp,15);
print(newTemp);
String[] art={"a","b","c"};
String[] atr1=(String[])arrayInc(atr,8);
print(str);
//修改数组大小
public Static Object arrayInc(Object obj,int len){
     Class<?> arr=obj.getClass().getComponentType();
     Object newArr=Array.newInstance(arr,len);
     int co=Array.getLength(obj);
     System.arraycopy(obj,0,newArr,0,co);
     return newArr
 }
//打印
public static void print(Object obj){
    Class<?> c=obj.getClass();
   if(!c.isArray()){
    return;
      }
   System.out.println("数组长度为:"+Array.getLength(obj));
    for(int i=0;i<Array.getLength(obj);i++){
     System.out.print(Array.get(obj,i)+"");
}
System.out.println();
 }

 4.将反射机制应用于工厂模式

package com.lj
interface fruit{
   public static void eat();
}

class Apple implements fruit{
public void eat(){
 System.out.println("Apple")
 }
}
class Orange implements fruit{
public void eat(){
 System.out.println("Orange")
 }
}
class Factory{
    public static fruit getInstance(String ClassName){
      fruit f=null;
      try{
       f=(fruit)Class.forName(ClassName).newInstance();
}catch(Exception e){
  e.printStackTrace();
}
return f;
}
}
public class Test{
         public static void main(String[] args)throws Exception{
                    friut f=Factory.getInstance("com.lj.Apple");
                     if(f!=null){ 
                        f.eat();
                    }
  }
}

  

 

posted @ 2020-11-05 16:03  烟笼寒山  阅读(70)  评论(0)    收藏  举报