Java高级特性--反射详解

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/zwt122755527/article/details/102723542

本人博客:https://cherishlife.com.cn/blog/22 有兴趣的朋友支持下,谢谢!

概述

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

java.lang.Class类是进行反射操作的源头所在,所有的反射操作都是通过这个类展开的。

 

类的声明

public final class Class<T> extends Object 
    implements Serializable, GenericDeclaration, Type, AnnotatedElement


Class类不能有子类,并且在jdk1.5之后引入了泛型技术(泛型在反射之中是非常糟糕的)。


这个类从jdk1.0开始提供的,这个类中的构造方法并不能被直接使用,而要想取得反射类的实例化对象,在Java里提供有三种类型:
1. 利用Object类之中的getClass()方法
方法:public final Class<?> getClass(),表示所有类的实例化对象都可以调用此方法。

Date date = new Date();
Class<?> cls = date.getClass();
System.out.println(cls);


在任何的开发中,这种调用getClass()的方法很少会出现在直接的编写形式上。

2. 使用“类.class”的形式取得反射的实例化对象

Class<?> cls = java.util.Date.class;
System.out.println(cls);


这样的操作形式只有在框架技术上才会使用到。
以上的两种操作都有一个本质的共同点:类必须首先存在,而后才可以进行反射的操作。

3. 利用Class类提供的方法实例化对象

public static Class<?> forName(String className) throws ClassNotFoundException
Class<?> cls = Class.forName("java.util.Date");
System.out.println(cls);


利用forName方法进行Class类的取得,最大的特征是可以在类不存在的时候保持程序编译的正确性。

利用反射实例化对象

利用发射实例化对象,在Class类中提供有如下方法:
 

public T newInstance() throws InstantiationException, IllegalAccessException
Class<?> cls = Class.forName("java.util.Date");
Object obj = cls.newInstance();
System.out.println(obj);

在开发中,如果是自己定义的接口,要取得实例化对象,不能直接采用关键字new利用对象的向上转型为接口实例化,而是应该采用工厂设计模式取得。

复杂工厂模式Demo

package com.demo;

interface Fruit {
    void eat();
}

class Apple implements Fruit {
    @Override
    public void eat() {
        System.out.println("eat apple");
    }
}
class Orange implements Fruit {
    @Override
    public void eat() {
        System.out.println("eat orange");
    }
}

class Factory {
    public static Fruit getInstance(String className) {
        try {
            Fruit fruit = (Fruit)Class.forName(className).newInstance();
            return fruit;
        } catch (Exception e) {
            return null;
        }
    }
}

public class Test {
    public static void main(String[] args) {
        Fruit f = Factory.getInstance("com.demo.Apple");
        f.eat();
    }
}

取得类定义结构:

类所在的包:
 

public Package getPackage()

类的声明方式:
取得完整类名称:包.类

public String getName()


只取得类名称:

public String getSimpleName()

类所实现的父类:

public Class<? super T> getSuperClass()

类所实现的接口:

public Class<?>[] getInterfaces()

构造方法

取得全部构造:

public Constructor<?>[] getConstructors() throws SecurityException

取得指定构造:(匹配的是参数类型)

public Constructor<T> getConstructor(Class<?>... parameterType) throws NoSuchMethodException, SecurityException

以上返回值都是java.lang.reflect.Constructor<T>类的对象,而在这个类中定义了如下方法:
- 取得构造方法修饰符:public int getModifiers()
- 取得构造方法名称:public String getName()
- 取得构造方法参数个数:public int getParameterCount()
- 取得构造方法参数类型:public Class<?>[] getParameterTypes()
- 取得构造方法抛出的异常类型:public Class<?>[] getExceptionTypes()
- 实例化对象:public T newInstance(Object ... initargs) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException


关于方法修饰符:modifiers
 

java.lang.reflect.Modifier
public static String toString(int modifiers)

取得方法

反射最大的用处(开发中),就是针对方法的操作。在反射机制中,普通方法可以在保存对象状态的情况下进行各种操作。

取得全部方法

本类与继承的方法:
public method[] getMethods() throws SecurityException
本类的方法:
public method[] getDeclaredMethods() throws SecurityException

取得指定方法

public method getMethod(String name, Class<?>... parameterTypes) throws NoSuchMethodException, SecurityException

java.lang.reflect.Method 方法类

取得方法修饰符:
public int getModifiers()
取得方法名称:
public String getName()
取得方法参数个数:
public int getParameterCount()
取得方法参数类型:
public Class<?>[] getParameterTypes()
调用指定方法:(必须有实例化对象,而后在设置参数)
public Object invoke(Object obj, Object... args) throws IllegalAccessException, IllegalArgumentException,InvocationTargetException
返回值的类型:
public Class<?> getReturnType()

反射调用:一个类必须要有一个实例化对象的情况下才能够调用类中的普通方法。

Class<?> cls = Class.forName("java.util.Date");
Object obj = cls.newInstance();
Method method1 = cls.getMethod("compareTo", Date.class);
Method method2 = cls.getMethod("toString");
System.out.println(method1.invoke(obj, new Date()));
System.out.println(method2.invoke(obj));

取得成员

反射最大的用处(开发中),就是针对方法的操作。在反射机制中,普通方法可以在保存对象状态的情况下进行各种操作。

取得全部成员:

获得本类声明的成员:
public Field[] getDeclaredFields() throws SecurityException
获得继承声明的成员:
public Field[] getFields() throws SecurityException

取得指定成员:

获得本类声明的成员:
public Field getDeclaredField(String name) throws NoSuchFieldException, SecurityException
获得继承声明的成员:
public Field getField(String name) throws NoSuchFieldException, SecurityException

java.lang.reflect.Field 是表示成员的类型

取得属性内容:
public Object get(Object obj) throws IllegalArgumentException, IllegalAccessException
取得属性类型:
public Class<?> getType()
设置属性:
public void set(Object obj, Object value) throws IllegalArgumentException, IllegalAccessException

解除封装:(Method,Field,Constructor的父类AccessibleObject)

public static void setAccessible(AccessibleObject[] array, boolean flag)


设置为true表示取消封装,默认是false。

猜你喜欢

转载自blog.csdn.net/zwt122755527/article/details/102723542