Java开发:反射机制

一、Java Reflection

Reflection(反射)是java被视为动态语言的关键(Java是静态语言,因为有了反射所以又被成为“准动态语言”)

二、重点:一个类只有一个Class对象

三、反射的优缺点

优点:可以实现动态创建对象和编译,体现出很大的灵活性
缺点:对性能有影响。使用反射基本上是一种解释操作,我们可以告诉JVM,我们希望做什么并且它满足我们的要求。
这类操作总是慢于 直接执行相同的操作。

四、获取Class类的实例

1、该方法最安全可靠,性能最高。
Class c1 = Student.class;
2、通过类的实例获取Class对象
Person student = new Student(“学生”);
Class c2 = student.getClass();
3、通过类名全路径获取Class对象
Class c3 = Class.forName(“com.baidu.baike.lesson.annotations_reflection.Student”);

public class RLesson002 {
    public static void main(String[] args) {
        try {
            Person student = new Student("学生");
            System.out.println(student.name);

            //推荐使用1
            Class c1 = Student.class;

            Class c2 = student.getClass();

            //推荐使用2
            Class c3 = Class.forName("com.baidu.baike.lesson.annotations_reflection.Student");

            //可以获取父类的class
            Class superclass = c1.getSuperclass();

            //c1、c2、c3的hashCode相同
            System.out.println(c1.hashCode());
            System.out.println(c2.hashCode());
            System.out.println(c3.hashCode());
            System.out.println(superclass);
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        }


    }
}

class Person {
    public String name;

    public Person(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                '}';
    }
}

class Student extends Person {

    public Student(String name) {
        super(name);
    }
}


五、几乎所有类型都有class对象

class:外部类,成员(成员内部类、静态内部类),局部内部类,匿名内部类
interface:接口
[]:数组
enum:枚举
annotation:注解@interface
primitive type:基本数据类型
void:方法


public class RLesson003 {
    public static void main(String[] args) {
        Class c1 = Object.class;//类
        Class c2 = Comparable.class;//接口
        Class c3 = String[].class;//一维数组
        Class c4 = int[][].class;//二维数组
        Class c5 = Override.class;//注解
        Class c6 = ElementType.class;//枚举
        Class c7 = Integer.class;//基本数据类型
        Class c8 = void.class;//方法
        Class c9 = Class.class;//Class

        System.out.println(c1);
        System.out.println(c2);
        System.out.println(c3);
        System.out.println(c4);
        System.out.println(c5);
        System.out.println(c6);
        System.out.println(c7);
        System.out.println(c8);
        System.out.println(c9);

    }

}

六、类加载内存分析


public class RLesson002 {
    public static void main(String[] args) {

        System.out.println(Person.m);
        Person p1 = new Person("小明");
    }
}

class Person {
    static {
        System.out.println("Person类的静态代码块初始化");
        m = 300;
    }

    static int m = 100;
    public String name;

    public Person(String name) {
        System.out.println("Person类的无参构造初始化");
        this.name = name;
    }
}

运行结果:
Person类的静态代码块初始化
100
Person类的无参构造初始化

Process finished with exit code 0

七、获取类的运行时结构


public class RLesson004 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException {
        Class c1 = Class.forName("com.baidu.baike.lesson.annotations_reflection.User");
        //获取类的名字
        System.out.println(c1.getName());//获取包名+类名
        System.out.println(c1.getSimpleName());//获取类型

        System.out.println("==========获取类的属性===========");
        System.out.println("------>获取public的属性");
        Field[] fields = c1.getFields();//获取public的属性
        for (Field field : fields) {
            System.out.println(field);
        }
        System.out.println("------>获取private+public的属性");
        fields = c1.getDeclaredFields();//获取private+public的属性
        for (Field field : fields) {
            System.out.println(field);
        }

        System.out.println("==========获取指定属性的值===========");
        Field fName = c1.getDeclaredField("name");
        System.out.println(fName);

        System.out.println("==========获取类的方法===========");
        System.out.println("------>获取public的方法");
        Method[] methods = c1.getMethods();
        for (Method method : methods) {
            System.out.println("public的方法" + method);
        }
        System.out.println("------>获取自定义的public+private方法");
        methods = c1.getDeclaredMethods();
        for (Method method : methods) {
            System.out.println("public+private的方法 -> " + method);
        }

        System.out.println("==========获取指定方法===========");
        Method getName = c1.getMethod("getName");
        Method setName = c1.getMethod("setName", String.class);
        System.out.println(getName);
        System.out.println(setName);

        System.out.println("==========获取构造器===========");
        System.out.println("-----------获取public的构造器");
        Constructor[] constructors = c1.getConstructors();
        for (Constructor constructor : constructors) {
            System.out.println(constructor);
        }
        System.out.println("-----------获取private+public的构造器");
        constructors = c1.getDeclaredConstructors();
        for (Constructor constructor : constructors) {
            System.out.println(constructor);
        }

        System.out.println("==========获取指定构造器===========");
        Constructor mConstructor = c1.getDeclaredConstructor(String.class, int.class, int.class);
        System.out.println(mConstructor);
    }
}

class User {
    private String name;
    private int age;
    public int sex;

    public User() {
    }

    private User(String name) {
        this.name = name;
    }

    public User(String name, int age, int sex) {
        this.name = name;
        this.age = age;
        this.sex = sex;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    private int getSex() {
        return sex;
    }

    private void setSex(int sex) {
        this.sex = sex;
    }
}

运行结果:
com.baidu.baike.lesson.annotations_reflection.User
User
==========获取类的属性===========
------>获取public的属性
public int com.baidu.baike.lesson.annotations_reflection.User.sex
------>获取private+public的属性
private java.lang.String com.baidu.baike.lesson.annotations_reflection.User.name
private int com.baidu.baike.lesson.annotations_reflection.User.age
public int com.baidu.baike.lesson.annotations_reflection.User.sex
==========获取指定属性的值===========
private java.lang.String com.baidu.baike.lesson.annotations_reflection.User.name
==========获取类的方法===========
------>获取public的方法
public的方法public java.lang.String com.baidu.baike.lesson.annotations_reflection.User.getName()
public的方法public void com.baidu.baike.lesson.annotations_reflection.User.setName(java.lang.String)
public的方法public int com.baidu.baike.lesson.annotations_reflection.User.getAge()
public的方法public void com.baidu.baike.lesson.annotations_reflection.User.setAge(int)
public的方法public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
public的方法public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
public的方法public final void java.lang.Object.wait() throws java.lang.InterruptedException
public的方法public boolean java.lang.Object.equals(java.lang.Object)
public的方法public java.lang.String java.lang.Object.toString()
public的方法public native int java.lang.Object.hashCode()
public的方法public final native java.lang.Class java.lang.Object.getClass()
public的方法public final native void java.lang.Object.notify()
public的方法public final native void java.lang.Object.notifyAll()
------>获取自定义的public+private方法
public+private的方法 -> public java.lang.String com.baidu.baike.lesson.annotations_reflection.User.getName()
public+private的方法 -> public void com.baidu.baike.lesson.annotations_reflection.User.setName(java.lang.String)
public+private的方法 -> public int com.baidu.baike.lesson.annotations_reflection.User.getAge()
public+private的方法 -> public void com.baidu.baike.lesson.annotations_reflection.User.setAge(int)
public+private的方法 -> private int com.baidu.baike.lesson.annotations_reflection.User.getSex()
public+private的方法 -> private void com.baidu.baike.lesson.annotations_reflection.User.setSex(int)
==========获取指定方法===========
public java.lang.String com.baidu.baike.lesson.annotations_reflection.User.getName()
public void com.baidu.baike.lesson.annotations_reflection.User.setName(java.lang.String)
==========获取构造器===========
-----------获取public的构造器
public com.baidu.baike.lesson.annotations_reflection.User(java.lang.String,int,int)
public com.baidu.baike.lesson.annotations_reflection.User()
-----------获取private+public的构造器
public com.baidu.baike.lesson.annotations_reflection.User(java.lang.String,int,int)
private com.baidu.baike.lesson.annotations_reflection.User(java.lang.String)
public com.baidu.baike.lesson.annotations_reflection.User()
==========获取指定构造器===========
public com.baidu.baike.lesson.annotations_reflection.User(java.lang.String,int,int)

八、动态创建对象

A、创建类的对象

调用Class对象的newInstance()方法。

  • 类必须有一个无参数的构造器
  • 类的构造器的访问权限需要足够

B、具体步骤

  • 通过Class类的getDeclaredConstructor(Class …parameterTypes)取得本类的指定形参类型的构造器。
  • 向构造器的形参中传递一个对象数组进去,里面包含了构造器中所需的各个参数
  • 通过Constructor实例化对象

C、示例代码

public class RLesson005 {
    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
        Class c1 = Class.forName("com.baidu.baike.lesson.annotations_reflection.User");

        //使用默认无参构造
        User user = (User) c1.newInstance();
        user.setName("小花");
        user.setAge(18);
        //获取private方法并赋值
        Method setSex = c1.getDeclaredMethod("setSex", int.class);
        //不能直接操作私有方法,将私有方法设为可见
        setSex.setAccessible(true);
        setSex.invoke(user, 2);
        System.out.println(user);


        //使用三个参数的构造器
        Constructor mConstructor = c1.getDeclaredConstructor(String.class, int.class, int.class);
         user = (User) mConstructor.newInstance("小王", 10, 8);
         //获取私有属性
        Field name = c1.getDeclaredField("name");
        //不能直接操作私有属性,将私有属性设为可见
        name.setAccessible(true);
        name.set(user, "小赵");
        System.out.println(user);
    }
}

class User {
    private String name;
    private int age;
    public int sex;

    public User() {
    }

    private User(String name) {
        this.name = name;
    }

    public User(String name, int age, int sex) {
        this.name = name;
        this.age = age;
        this.sex = sex;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    private int getSex() {
        return sex;
    }

    private void setSex(int sex) {
        this.sex = sex;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", sex=" + sex +
                '}';
    }
}


执行结果:
User{name='小花', age=18, sex=2}
User{name='小赵', age=10, sex=8}

九、获取注解信息

A、应用场景

利用注解和反射完成类和表结构的映射关系
在这里插入图片描述

B、示例代码


public class ALesson002 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
        Class c1 = Class.forName("com.baidu.baike.lesson.annotations_reflection.StudentAL2");
        Annotation[] c1_annotation = c1.getDeclaredAnnotations();
        for (Annotation annotation : c1_annotation) {
            System.out.println(annotation);
        }
        System.out.println("======================");
        Field field_name = c1.getDeclaredField("name");
        FieldName field_nameDeclaredAnnotation = field_name.getDeclaredAnnotation(FieldName.class);
        System.out.println(field_nameDeclaredAnnotation.columnName() + ",type->" + field_nameDeclaredAnnotation.type() + ",length->" + field_nameDeclaredAnnotation.length());
    }
}

@TableName("studeng_al2")
class StudentAL2 {
    @FieldName(columnName = "f_name", type = "1", length = 10)
    private String name;
    @FieldName(columnName = "f_age", type = "2", length = 3)
    private int age;
    @FieldName(columnName = "f_sex", type = "3", length = 2)
    private int sex;
}

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface TableName {
    String value();
}

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface FieldName {
    String columnName();

    String type();

    int length();
}

运行结果:
@com.baidu.baike.lesson.annotations_reflection.TableName(value=studeng_al2)
======================
f_name,type->1,length->10

结束

猜你喜欢

转载自blog.csdn.net/android157/article/details/128141582