java笔记--反射机制之基础总结与详解

一.反射之实例化Class类的5种方式:

java的数据类型可以分为两类,即引用类型和原始类型(即基本数据类型)。
对于每种类型的对象,java虚拟机会实例化不可变的java.lang.Class对象。
它提供了在运行时检查对象属性的方法,这些属性包括它的成员和类型信息。

更重要的是Class对象是所有反射API的入口。

Class类是泛型类,可以使用@SuppressWarnings("unchecked")忽略泛型或者使用Class<V>类型。

获得Class对象的5种方式:

1."Object.getClass()"   : 如果一个类的对象可用,则最简单的获得Class的方法是使用Object.getClass()。
                                    当然,此方式只对引用类型有效。

2. ".class"------------- : 如果类型可用但没有对象,则可以在类型后加上".class"来获得Class对象。这也是使原始类型
                                    获得Class对象最简单的方式:
3."Class.forName()"---:  如果知道类的全名,则可以使用静态方法Class.forName()来获得Class对象,它不能用在原始类型上,

但是可以用在原始类型数组上。(注:此方式会抛出ClassNotFoundException异常)
4. "包装类的TYPE域"-----:  每一个原始类型和void都有包装类。利用其TYPE域就可以获得Class对象。

5."以Class为返回值的方法": 如获取内部类的getDeclaredClasses()方法,此时返回一个对象数组

--支持知识共享,转载请标注地址"http://www.cnblogs.com/XHJT/p/3915221.html  "——和佑博客园,谢谢~~--

代码实例:

package com.xhj.reflection_excetion;

/**
 * 反射之实例化Class类的5种方式
 *
 * @author XIEHEJUN
 *
 */
public class InstantiateClassObject {

    @SuppressWarnings("rawtypes")
    public static void main(String[] args) throws ClassNotFoundException {
        System.out.print("第一种方式--用Object.getClass()方法获取到的String类的对象为: ");
        Class class1 = new String().getClass();
        System.out.println(class1.getName());    

        System.out.print("第二种方式--用.class()方法获取到的String类的对象为: ");
        class1 = String.class;
        System.out.println(class1.getName());

        System.out.print("第三种方式--用.forName()方法获取到的String类的对象为: ");
        class1 = Class.forName("java.lang.String");
        System.out.println(class1.getName());

        System.out.print("第四种方式--用包装类的TYPE域获取到的Integer类的对象为: ");
        class1 = Integer.TYPE;
        System.out.println(class1.getName());

        System.out.println("第五种方式--用getDeclaredClasses()获取String类的内部类对象:");
        Class<?>[] clazz = new String().getClass().getDeclaredClasses();
        for (Class<?> class2 : clazz) {
            System.out.println("\t"+class2);
        }

    }

}

结果为:

注:除了java.lang.reflect.ReflectPermission和java.lang.reflect包外,所有类都没有公共的

构造方法。为了获得这些类的对象,必须使用Class类中适当的方法,对于不同的数据类型,Class

对象的获得方式是不同。

二.反射之查看类的定义:

通常类的声明包括常见修饰符(public,protected,private,abstract,static,final,strictfp等)、

类的名称、类的泛型参数、类的继承类(实现的接口)、类的注解等信息。

Class类的实例表示正在运行的Java应用程序中的类和接口:

枚举是一种类,注释是一种接口。

每一个数组属于被映射为Class对象的一个类,所有具有相同元素类型和维数的数组都共享该Class对象;

基本数据类型和关键字void也表示为Class对象。

Class没有公共的构造方法。

Class对象是在加载类时由Java虚拟机以及通过调用类加载器中的defineClass方法自动构造的。

   Class类常用方法:

    forName(String className)-: 根据给定的名称获得Class对象

getAnnotations()------------: 返回此Class对象上存在的注释

getCanonicalName() --------: 返回Java Language Specification 中所定义的底层类的规范化名称

getGenericInterfaces()------: 返回泛型形式的对象类所实现的接口

getGenericSuperclass() -----: 返回泛型形式的对象类所直接继承的超类

getModifuers() --------------: 返回此类或接口以整数编码的Java语言修饰符

getTypeParameters() -------: 按声明顺序返回TypeVariable对象的一个数组

注:Java语言预定义的注解只有@Deprecated可以在运行时获得。   
   
实例代码:

package com.xhj.reflection_excetion;

import java.lang.annotation.Annotation;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;

/**
 * 查看类的定义
 *
 * @author XIEHEJUN
 *
 */
public class CheckClassStatement {

    public static void main(String[] args) throws ClassNotFoundException {
        Class<?> classtest = Class.forName("java.util.ArrayList");
        System.out.println("1.根据给定的名称获得Class对象:" + classtest.getName());
        Annotation[] annotations = classtest.getAnnotations();
        System.out.print("2.获取此对象上的注解为:");
        if (annotations.length > 0) {
            for (Annotation annotation : annotations) {
                System.out.println(annotation + "\t");
            }
        } else {
            System.out.println("空");
        }

        System.out.println("3.获得Java语言规范化名称:" + classtest.getCanonicalName());

        System.out.println("4.获取类上的修饰符:共有" + classtest.getModifiers()
                + "个,为: " + Modifier.toString(classtest.getModifiers()));

        TypeVariable<?>[] typeV = classtest.getTypeParameters();
        System.out.print("5.在对象上获取到的泛型是:");
        if (typeV.length > 0) {
            for (TypeVariable<?> typeVariable : typeV) {
                System.out.println(typeVariable);
            }
        } else {
            System.out.println("空");
        }

        System.out.println("6.在对象上获取到的接口为:");
        // 使用getInterfaces()不包含泛型;使用getGenericInterfaces包含泛型
        Type[] intefaces = classtest.getGenericInterfaces();
        if (intefaces.length > 0) {
            for (Type type : intefaces) {
                System.out.println("\t" + type);
            }
        } else {
            System.out.println("空");
        }
        Class class2 = classtest.getSuperclass();
        System.out.print("7.在对象上获取直接继承类:");
        if (class2 != null) {
            System.out.println(class2);
        } else {
            System.out.println("空");
        }

    }
}

结果为:

注:getSuperclass()方法也不能获得有泛型信息的父类

三.反射之获得Class对象表示实体的名称

对于不同类型的对象,其Class对象的名称是不同的,反过来说就是从这个名称就可以知道该对象的类型。

注:

1.如果此类对象表示的是非数组类型的引用类型,则返回该类的二进制名称。

2.如果此类对象表示一个基本类型或者void,则返回其对应的Java语言的关键字的字符串。

3.如果此类对象表示一个数组类,名字的内部形式为"[元素编码",其深度为几维,就有几个"["。

其元素类型编码为:

——————————————————————————————————————————————————

元素类型                       编 码          
           boolean                         Z

byte                              B

char                              C

short                             S

int                                 I

float                              F

double                           D

long                              J

class or interfaces       Lclassname(即当元素是引用类型或者接口的时候,编码为"L+类名")

____________________________________________________

实例代码:

package com.xhj.reflection_excetion;

/**
 * 获取对象实体的名称
 *
 * @author XIEHEJUN
 *
 */
public class GetClassEntityName {
    /**
     * 数组元素类型编码为:
     * 元素类型                       编码
     * boolean                     Z
     * byte                       B
     * char                       C
     * short                      S
     * int                        I
     * float                      F
     * double                     D
     * long                       J
     * class or interfaces    Lclassname(即当元素是引用类型或者接口的时候,编码为"L+类名")
     */
    public static void main(String[] args) {
        System.out.println("获取非数组类型的引用类型,返回该类的二进制名称: "
                + new String().getClass().getName());
        System.out.println("获取基本类型,返回其对应的Java语言的关键字的字符串: "
                + int.class.getName());
        System.out.println("获取void类型,返回其对应的Java语言的关键字的字符串: "
                + void.class.getName());
        System.out.println("获取一维数组类型的基本类型,返回‘[+元素编码‘: "
                + new int[2].getClass().getName());
        System.out.println("获取一维数组类型的引用类型,返回‘[+元素编码‘: "
                + new String[2].getClass().getName());
        System.out.println("获取二维数组类型的基本类型,返回‘[+元素编码‘: "
                + new int[2][3].getClass().getName());
        System.out.println("获取二维数组类型的引用类型,返回‘[+元素编码‘: "
                + new String[2][3].getClass().getName());
        System.out.println("用getCanonicalName()获取二维数组类型的基本类型,返回数组名称"
                + new int[2][3].getClass().getCanonicalName());
        System.out.println("用getCanonicalName()获取二维数组类型的引用类型,返回数组名称"
                + new String[2][3].getClass().getCanonicalName());
    }

}

结果为:

注:
对于数组来说,用getCanonicalName()方法可以获取的到数组的名称,且比较容易接受和辨认

四.反射之查看类的成员

我们要查看类的定义,首先想到的当然是API文档,但若是找不到API文档又该如何呢?此时就要用到Java的反射机制了。

另外我们在无法查看源代码的情况下,也可以通过反射机制查看类的成员,包括"域,构造方法,普通方法和内部类"等。

主要用到的方法:

    getConstructors() -------: 返回由该类对象的所有构造方法组成的数组

getDeclaredFields() -----:  返回由该类对象的所有非继承域组成的数组

getDeclaredMethods() -- :  返回由该类对象的所有非继承方法组成的数组

getFields() -------------- :  返回由该类对象的所有公共域组成的数组

getMethod() -------------:  返回由该类对象的所有公共方法组成的数组

代码实例:

package com.xhj.reflection_excetion;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

/**
 * 查看类的成员
 *
 * @author XIEHEJUN
 *
 */
public class CheckClassMembers {

    public static void main(String[] args) {
        Class<?> strclass = new String().getClass();

        // 查看构造方法
        System.out.println(strclass.getName() + "的构造方法有:");
        Constructor<?>[] constructors = strclass.getConstructors();
        if (constructors.length > 0) {
            for (Constructor<?> constructor : constructors) {
                System.out.println("\t" + constructor);
            }
        } else {
            System.out.println("空");
        }
        // 查看非继承域
        System.out.println(strclass.getName() + "的非继承域有:");
        Field[] declaredFields = strclass.getDeclaredFields();
        if (declaredFields.length > 0) {
            for (Field field : declaredFields) {
                System.out.println("\t" + field);
            }
        } else {
            System.out.println("空");
        }

        // 查看非继承方法
        System.out.println(strclass.getName() + "的非继承方法有:");
        Method[] declaredMethods = strclass.getDeclaredMethods();
        if (declaredMethods.length > 0) {
            for (Method method : declaredMethods) {
                System.out.println("\t" + method);
            }
        } else {
            System.out.println("空");
        }

        // 查看所有公共域
        System.out.println(strclass.getName() + "的所有域有:");
        Field[] fields = strclass.getFields();
        if (fields.length > 0) {
            for (Field field : fields) {
                System.out.println("\t" + field);
            }
        } else {
            System.out.println("空");
        }

        // 查看所有公共的方法
        System.out.println(strclass.getName() + "的所有继承方法有:");
        Method[] methods = strclass.getMethods();
        if (methods.length > 0) {
            for (Method method : methods) {
                System.out.println("\t" + method);
            }
        } else {
            System.out.println("空");
        }
    }

}

结果为:

(打印出来的数据太多,这里之展示部分结果~)

注:对于私有域或方法,如果有安全管理器,可能会报异常。

五:反射之查看内部类消息

Class类的getDeclaredClasses()方法返回Class对象的一个数组,这些对象反映声明为该Class对象
所表示的类的成员的所有类和接口,包括该类所声明的公共、保护、默认(包)访问及私有类和接口,

但不包括继承的类和接口。若该类不将任何类或接口声明为成员,或者该对象表示基本类型、数组类或

void,则该方法返回一个长度为0的数组。

public Class<?> [] getDeclaredClasses() throws SecurityException

注:利用Class类的getDeclaredClasses()方法可以获得一个数组,其中的每一个成员代表一个内部类的类对象。

然后我们可以像获取普通类的信息一样,获取到内部类的信息。

代码实例:

package com.xhj.reflection_excetion;

import java.lang.reflect.Field;
import java.lang.reflect.Method;

/**
 * 查看内部类的消息
 *
 * @author XIEHEJUN
 *
 */
public class CheckInnerClass {

    public static void main(String[] args) {
        Class<?> clazz = new String().getClass();
        Class[] class1 = clazz.getDeclaredClasses();
        for (int i = 0; i < class1.length; i++) {
            Class<?> innerclass = class1[i];
            System.out
                    .println("================================================================");
            System.out.println("内部类" + i + "为: " + innerclass.getName());

            System.out.println("内部类" + i + "的父类为:"
                    + innerclass.getSuperclass().getName());

            System.out.print("内部类" + i + "的所有公共域为:");
            Field[] field = innerclass.getFields();
            if (field.length > 0) {
                System.out.println();
                for (Field field2 : field) {
                    System.out.println("\t" + field2);
                }
            } else {
                System.out.println("空");
            }

            System.out.print("内部类" + i + "的非继承域为:");
            Field[] declaredfield = innerclass.getDeclaredFields();
            if (declaredfield.length > 0) {
                System.out.println();
                for (Field field2 : declaredfield) {
                    System.out.println("\t" + field2);
                }
            } else {
                System.out.println("空");
            }

            System.out.print("内部类" + i + "的所有公共方法为:");
            Method[] methods = innerclass.getMethods();
            if (methods.length > 0) {
                System.out.println();
                for (Method method : methods) {
                    System.out.println("\t" + method);
                }
            } else {
                System.out.println("空");
            }

            System.out.print("内部类" + i + "的非继承方法为:");
            Method[] declaredmethods = innerclass.getDeclaredMethods();
            if (declaredmethods.length > 0) {
                System.out.println();
                for (Method method : declaredmethods) {
                    System.out.println("\t" + method);
                }
            } else {
                System.out.println("空");
            }

        }

    }

}

结果为:

(打印出来的数据太多,这里之展示部分结果~)

六.反射之按继承层次对类排序

Java提供了instanceof运算符来比较两个类(或接口)之间是否存在继承关系。

但是对于多个类来说,这种方法是很麻烦的。这时候,我们要做的应该是利用

java的反射机制来对存在继承关系的类进行排序。

主要方法:

TreeSet<E> 是基于TreeMap的NavigableSet实现的。它使用元素的自然顺序对

元素进行排序,或者根据创建set时提供的Comparator进行排序,具体取决于

使用的构造方法。本节采用Class类中的isAssignableFrom()方法来判断当前

Class 对象所表示的类与给定的Class对象所表示的类之间的关系,若相同或

是父类则返回true,否则返回false。

public boolean isAssignableFrom(Class<?> clazz)

   
注:Java中与排序相关的接口有Comparable和Comparator。这两个接口通过对象之

间比较的结果--一个有符号的整数来比较对象的大小。实现任何一个接口都可

以让对象具有排序的能力。固可以用TreeSet也可以用Arrays.sort()来进行排序。

代码实例:

package com.xhj.reflection_excetion;

import java.awt.Container;
import java.util.Comparator;
import java.util.TreeSet;

import javax.swing.JComponent;
import javax.swing.JPanel;

/**
 * 比较并将类按继承关系排序
 *
 * @author XIEHEJUN
 *
 */
public class CompareClasses implements Comparator<Class<?>> {

    @Override
    public int compare(Class<?> o1, Class<?> o2) {
        if (o1.equals(o2)) {
            return 0;
        } else if (o1.isAssignableFrom(o2)) {
            return -1;
        } else if (o2.isAssignableFrom(o1)) {
            return 1;
        } else {
            throw new IllegalArgumentException(o1+"和"+o2+"两个类之间没有联系");
        }
    }

    public static void main(String[] args) {
        TreeSet<Class<?>> treeSet = new TreeSet<Class<?>>(
                new CompareClasses());
        System.out.println("添加类——JComponent.class");
        treeSet.add(JComponent.class);
        System.out
        .println("添加类——Container.class");
        treeSet.add(Container.class);
        System.out.println("添加类——JPanel.class");
        treeSet.add(JPanel.class);
        System.out.println("=================排序后为=====================");
        for (Class<?> class1 : treeSet) {
            System.out.println(class1);
        }
    }

}

结果为:

java笔记--反射机制之基础总结与详解

时间: 2024-12-28 17:01:27

java笔记--反射机制之基础总结与详解的相关文章

Java反射机制Class类的用法详解

本文转自http://blog.sina.com.cn/s/blog_6c9536b90100rqh4.html,感谢作者 java的Class类是java反射机制的基础,通过Class类我们可以获得关于一个类的相关信息,下面我们来了解一下有关java中Class类的相关知识! java.lang.Class是一个比较特殊的类,它用于封装被装入到JVM中的类(包括类和接口)的信息. 当一个类或接口被装入的JVM时便会产生一个与之关联的java.lang.Class对象,可以通过这个Class对象

java笔记之图形类----非组件容器详解

Java的非容器组件: 加入非容器步骤: 1.创建一个Jframe 2.创建面板Jpanel 3.将面板加入到Jframe中 4.添加Jlabel标签 5.新建组件 a:JTextField  文本输入框  可指定输入框大小 b:JPasswordField 文本密文输入 JPasswordField passwordField=new JPasswordField(10); c:JRadioButton 单选按钮 JRadioButton man = new JRadioButton("男&q

JAVA的反射机制学习笔记(二)

上次写JAVA的反射机制学习笔记(一)的时候,还是7月22号,这些天就瞎忙活了,自己的步伐完全被打乱了~不能继续被动下去,得重新找到自己的节奏. 4.获取类的Constructor 通过反射机制得到某个类的构造器,然后调用该构造器创建该类的一个实例 Class<T>类提供了几个方法获取类的构造器. public Constructor<T> getConstructor(Class<?>... parameterTypes) 返回一个 Constructor 对象,它反

java的反射机制

一.java的反射机制浅谈 最近研究java研究得很给力,主要以看博文为学习方式.以下是我对java的反射机制所产生的一些感悟,希望各位童鞋看到失误之处不吝指出.受到各位指教之处,如若让小生好好感动,说不定会请各位吃饭哦! 1.何谓反射机制 根据网文,java中的反射机制可以如此定义: JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法:这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制. 2.反射

Java 类反射机制分析

一.反射的概念及在Java中的类反射 反射主要是指程序可以访问.检测和修改它本身状态或行为的一种能力.在计算机科学领域,反射是一类应用,它们能够自描述和自控制.这类应用通过某种机制来实现对自己行为的描述和检测,并能根据自身行为的状态和结果,调整或修改应用所描述行为的状态和相关的语义. 在Java中的反射机制,被称为Reflection.(大家看到这个单词,第一个想法应该就是去开发文档中搜一下了.)它允许运行中的Java程序对自身进行检查,并能直接操作程序的内部属性或方法.Reflection机制

java笔记--反射进阶之总结与详解

一.反射进阶之动态设置类的私有域 "封装"是Java的三大特性之一,为了能更好保证其封装性,我们往往需要将域设置成私有的, 然后通过提供相对应的set和get方法来操作这个域.但是我们仍然可以用java的反射机制来 修改类的私有域,由于修改类的私有域会破坏Java"封装"的特性,故请慎重操作. 主要技术:     Field类提供有关类或接口的单个字段的信息,以及对它的动态访问权限.     访问的字段可能是一个类(静态)字段或实例字段.             常

深入理解java的反射机制

今天将从以下4方面来系统的学习一下java的反射机制: java反射是什么 java反射(Reflection)底层实现原理 java反射的简单演示 java反射的应用场景 1,java反射是什么 首先大家应该先了解两个概念,编译期和运行期,编译期就是编译器帮你把源代码翻译成机器能识别的代码,比如编译器把java代码编译成jvm识别的字节码文件,而运行期指的是将可执行文件交给操作系统去执行,JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够

java利器------反射机制

java反射的概念:java的反射机制是指在运行状态下,对于一个类来说,可以得到这个类的所有方法和属性.对于一个对象来说,可以调用这个对象的人和方法和属性. 反射机制首先会拿到该类的字节码文件(Class文件),然后反向获取这个类的所有信息.(注意:一个类型的类在运行中,只产生一个class文件) 既然反射的前置条件是获取class类,所以不得不提出获取class的方法. 获取class的几种方式: (1)Persion p=new Persion(); Class c=p.getClass()

Java中反射机制和Class.forName、实例对象.class(属性)、实例对象getClass()的区别(转)

一.Java的反射机制   每个Java程序执行前都必须经过编译.加载.连接.和初始化这几个阶段,后三个阶段如下图:  其中 i.加载是指将编译后的java类文件(也就是.class文件)中的二进制数据读入内存,并将其放在运行时数据区的方法区内,然后再堆区创建一个Java.lang.Class对象,用来封装类在方法区的数据结构.即加载后最终得到的是Class对象,并且更加值得注意的是:该Java.lang.Class对象是单实例的,无论这个类创建了多少个对象,他的Class对象时唯一的!!!!.