反射机制

反射

能够分析“类”(不是对象)能力的程序称为反射(reflective)

  • 运行中分析类的能力
  • 运行中查看对象
  • 实现通用的数组操纵代码
  • 利用Method对象

Class 类

在程序运行期间,Java运行时系统始终为 所以对象维护一个 被称为运行时的类型标识。这个
信息跟踪着每个对象所属的类。虚拟机利用运行时类型信息选择相应的方法执行。

Object类中的getClass()方法将会返回一个Class类型的实例。
如下是源代码,该方法是一个不被允许重写的方法。

    /**
     * Returns the runtime class of this {@code Object}. The returned
     * {@code Class} object is the object that is locked by {@code
     * static synchronized} methods of the represented class.
     *
     * <p><b>The actual result type is {@code Class<? extends |X|>}
     * where {@code |X|} is the erasure of the static type of the
     * expression on which {@code getClass} is called.</b> For
     * example, no cast is required in this code fragment:</p>
     *
     * <p>
     * {@code Number n = 0;                             }<br>
     * {@code Class<? extends Number> c = n.getClass(); }
     * </p>
     *
     * @return The {@code Class} object that represents the runtime
     *         class of this object.
     * @see    Class Literals, section 15.8.2 of
     *         <cite>The Java™ Language Specification</cite>.
     */
    public final native Class<?> getClass();  

三种获得* 类类型 *实例 的方法

Object object = new Test();
System.out.println(object.getClass().getName());  // 将会输出 yang.Test (yang是我的包名字)

String className = "java.util.Date";
Class c1 = Class.forName(className);    // 获得当前类类型信息

Class c1 = Date.class;

一个Class 对象实际上表示的是一个类型,而这个类型未必一定是一种类。例如:int.class
虚拟机为* 每种类型(基本类型到每一个类)* 管理一个Class对象

Class c = int.class
c = Enum.class  
c = void.class
c = boolean.class
c = double.class
c = float.class
c = Float.class
c = new Float(3.4F).getClass
c = Class.forName("java.awt.Button")

public @interface Ann {
}

c = Ann.class;
// 类型:从基本类型、甚至 void 、boolean类型到数组 int[] 到类到接口到枚举enum到注解都是类型,每种类型都有一个Class对象维护信息。
//我们不可以访问这个对象(因为是私有的),它是由虚拟机生成的,引用这个对象方式非常多(如上)。
// <基类和子类是两种类型>有两个Class对象。
if(e.getClass() == EObject.class)   //判断对象`e`是不是`EObject`类类型的对象

利用反射分析类的能力

java.lang.reflect
Field Method Constructor分别用于描述类的域、方法、构造器

public class ReflectionTest
{
   public static void main(String[] args)
   {
      // read class name from command line args or user input
      String name;
      if (args.length > 0) name = args[0];
      else
      {
         Scanner in = new Scanner(System.in);
         System.out.println("Enter class name (e.g. java.util.Date): ");
         name = in.next();
      }
      try
      {
         // print class name and superclass name (if != Object)
         Class cl = Class.forName(name);
         Class supercl = cl.getSuperclass();
         String modifiers = Modifier.toString(cl.getModifiers());
         if (modifiers.length() > 0) System.out.print(modifiers + " ");
         System.out.print("class " + name);
         if (supercl != null && supercl != Object.class) System.out.print(" extends "
               + supercl.getName());    // Java是单进程方式,所以“实现接口”不算继承方法,只算一种多态性质。

         System.out.print("\n{\n");
         printConstructors(cl);
         System.out.println();
         printMethods(cl);
         System.out.println();
         printFields(cl);
         System.out.println("}");
      }
      catch (ClassNotFoundException e)
      {
         e.printStackTrace();
      }
      System.exit(0);
   }
   public static void printConstructors(Class cl)
   {
      Constructor[] constructors = cl.getDeclaredConstructors();
      for (Constructor c : constructors)
      {
         String name = c.getName();
         System.out.print("   ");
         String modifiers = Modifier.toString(c.getModifiers());
         if (modifiers.length() > 0) System.out.print(modifiers + " ");         
         System.out.print(name + "(");
         // print parameter types
         Class[] paramTypes = c.getParameterTypes();
         for (int j = 0; j < paramTypes.length; j++)
         {
            if (j > 0) System.out.print(", ");
            System.out.print(paramTypes[j].getName());
         }
         System.out.println(");");
      }
   }
   public static void printMethods(Class cl)
   {
      Method[] methods = cl.getDeclaredMethods();
      for (Method m : methods)
      {
         Class retType = m.getReturnType();
         String name = m.getName();
         System.out.print("   ");
         // print modifiers, return type and method name
         String modifiers = Modifier.toString(m.getModifiers());
         if (modifiers.length() > 0) System.out.print(modifiers + " ");         
         System.out.print(retType.getName() + " " + name + "(");
         // print parameter types
         Class[] paramTypes = m.getParameterTypes();
         for (int j = 0; j < paramTypes.length; j++)
         {
            if (j > 0) System.out.print(", ");
            System.out.print(paramTypes[j].getName());
         }
         System.out.println(");");
      }
   }
   public static void printFields(Class cl)
   {
      Field[] fields = cl.getDeclaredFields();
      for (Field f : fields)
      {
         Class type = f.getType();
         String name = f.getName();
         System.out.print("   ");
         String modifiers = Modifier.toString(f.getModifiers());
         if (modifiers.length() > 0) System.out.print(modifiers + " ");         
         System.out.println(type.getName() + " " + name + ";");
      }
   }
}

复制数组的好方法

    public static Object[] badCopyOf(Object a[], int newLength) {
        Object[] newArray = new Object[newLength]; // 一个对象数组无法转换成实际对象数组

        // 设有数组 A[] array = new A[10];
        // array是一对象(类型为数组,元素类型为A)
        // Object[] arrayTemp = (Object[]) array; // 这是可以的
        // Object arrayT = (Object) array; // 可以
        // 上述也可以转回去,我们始终要关注 new 的实际对象是谁(反射是最好的查看机制)。

// 阿猫阿狗(Object)都可以看家,但这个家究竟是谁的?利用反射机制。

        System.arraycopy(a, 0, newArray, 0, Math.min(a.length, newLength));
        return newArray;  // 转不会原始实际数组对象类型
    } 

    /**
     * A good method of Array copy
     * @param a
     * @param newLength
     * @return
     */
    public static Object goodCopyOf(Object a, int newLength) {
        Class<?> c = a.getClass();
        if(!c.isArray()) return null;
        Class<?> componentType = c.getComponentType(); // Returns the Class representing the component type of an array.
        int length = Array.getLength(a);
        Object newArray = Array.newInstance(componentType, newLength);
        System.arraycopy(a, 0, newArray, 0, Math.min(length, newLength));
        return newArray;
    }  

实例

public static void main(String[] args) {
        Object object = new Object[10];
        if(object.getClass().isArray()) {
            Object[] objects = (Object[]) object;
            for(int i=0; i<objects.length; i++){
                objects[i] = "Fuck you!";
            }
            for (Object objStr : objects) {
                if(objStr.getClass() == String.class){
                    System.out.println(objStr.toString());
                }
                // 或者
//                System.out.println(objStr);
            }
        }  

public class Test{
    public static void main(String[] args) {
        Object object = new Object[10];
        if(object.getClass() == String[].class) {    // 条件不成立
            Object[] objects = (Object[]) object;
            for(int i=0; i<objects.length; i++){
                objects[i] = "Fuck you!";
            }
            for (Object objStr : objects) {
//                if(objStr.getClass() == String.class){
//                    System.out.println(objStr.toString());
//                }
//                // 或者
                System.out.println(objStr);
            }
        }

    }  

    public static void main(String[] args) {
        Object object = new Object[10];
        if(object.getClass() == Object[].class) {    // 可以的
            Object[] objects = (Object[]) object;
            for(int i=0; i<objects.length; i++){
                objects[i] = "Fuck you!";
            }
            for (Object objStr : objects) {
//                if(objStr.getClass() == String.class){
//                    System.out.println(objStr.toString());
//                }
//                // 或者
                System.out.println(objStr);
            }
        }

    }  

Java独特的方法调用机制(不太好,容易出错)

public class Test{
    public static void main(String[] args) {
        try {
            Method out = Test.class.getMethod("out", String.class);
            out.invoke(new Test(), "OK men and girls");
        } catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
            e.printStackTrace();
        }

    }

    public void out(String str){
        System.out.println(str);
    }
}  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值