Java--Class类相关与反射重温

作者: androidjp | 来源:发表于2016-11-05 23:05 被阅读770次

一、注意点

  • 面向对象的世界中,万事万物皆对象。
  • Java中的类,是java.util.Class类的实例对象
  • 类的类类型,可从以下三种方式得到:
    1. Class<T> clazz = T.class;【因为每个.java文件在被编译成.class文件之后,T类内部就生成了一个静态属性,也就是T.class,它保存了这个类的基本信息】
    2. Class<T> clazz = t.getClass(); 【底层是native方法,用Java声明,用C语言实现,最终在Java中实现,其实就是获取这个静态属性】
    3. Class<T> clazz = Class.forName("类的全称"); 【代表动态加载类】

    动态实现装载类的方式:
    1. 隐式装载:new一个对象时,JRE检查并自动加载
    2. 显式装载:①Class.forName()ClassLoader.loadClass()

  • 基本数据类型和void关键字都存在类类型。
  • Class.getCanonicalName() 返回的是Java Language Specification中定义的基础类的规范化名称,换句话,就是返回全类名,没有就返回null。

二、Class类能给我们什么信息(常见):

  • 获取并打印所有属性信息【访问权限+属性类名+属性名】
public static Field[] getFieldList(Class clazz) {
    Field[] fields = clazz.getDeclaredFields();///获取类中所有的属性(忽略访问修饰符)
    for (Field fieid : fields) {
        Type type = fieid.getType();///获取属性类型
        System.out.println(Modifier.toString(fieid.getModifiers())+" "+type.getTypeName() + " " + fieid.getName());
    }
    return fields;
}

关键点:

  • Class.getDeclaredFields():Field[] : 获取类中所有的属性(忽略访问修饰符)

  • Fieid.getType():Type : 获取属性类型

  • 获取所有方法信息【访问权限+方法名+ 返回值类型 + 方法参数类型】

public static Method[] getMethodList(Class clazz) {
    Method[] methods = clazz.getDeclaredMethods();
    for (Method method : methods) {
        ///分析每一个方法
        getMethodMsg(method);
    }
    return methods;
}
/**
 * 获取Method的返回值类型和参数类型等信息
 * @param method
 */
public static void getMethodMsg(Method method) {
    StringBuilder sb = new StringBuilder();
    ///获取访问权限
    sb.append(Modifier.toString(method.getModifiers())+" ");
    ///返回值类型
    Class<?> returnType = method.getReturnType();
    ////参数类型
    Class[] paramsTypeList = method.getParameterTypes();
    sb.append(returnType.getName()).append("
 ").append(method.getName()).append("(");
    for (Class paramsType : paramsTypeList) {
        sb.append(paramsType.getName()).append(",");
    }
    sb.append(")");
    ///删除多余的","号
    if (sb.lastIndexOf(",") == sb.length() - 1) {
        sb.delete(sb.length() - 2, sb.length() - 1);
    }
    System.out.println(sb.toString());
}

关键点:

  • Class.getDeclaredMethods():Method[] : 获取类中所有的方法(忽略访问修饰符)

  • Method.getParameterTypes():Class[] : 获取方法的参数类类型列表

  • Method.getReturnType():Class : 获取方法的返回值类型

  • 获取构造函数信息【函数名+参数类型】

public static void getConstructorMsg(Object obj) {
    Class clazz = obj.getClass();
    ///封装了构造函数的信息
    Constructor[] constructors = clazz.getDeclaredConstructors();
    for (Constructor item:constructors){
        System.out.print(item.getName()+"(");
        Class[] paramTypes = item.getParameterTypes();
        for (Class type: paramTypes){
            System.out.print(type.getName()+",");
        }
        System.out.println(")");
    }
}

关键点:

  • Class.getDeclaredConstructors():Constructor[] : 获取这个类中所有的构造函数信息(每一个Constructor类对象拥有其中一个构造函数的信息)

  • Constructor.getParameterTypes(): Class[] : 获取这个构造函数的参数类类型列表

  • 调用无参构造方法生成类对象

//动态生成类对象(无参构造函数)
Class<MyObj> clazz = (Class<MyObj>)MyObj.getClass();
T obj = clazz.newInstance();
  • 调用有参构造方法生成类对象
//动态生成类对象(有参构造函数)
Class[] classes = new Class[]{Integer.class, String.class};
Object[] values = new Object[]{100, "hello world"};
Constructor<C> constructor = clazz.getDeclaredConstructor(classes);
C res = (C) constructor.newInstance(values);
  • 对象类型匹配
    方式一:对象 instanceof 类型
如:
Animal dog = new Dog();///Dog是Animal的子类
boolean b = dog instanceof Dog;//判断dog这个对象是不是Dog类型的实例,结果为true

方式二:class对象.isInstance(类对象)

如:
Animal dog = new Dog();///Dog是Animal的子类
boolean b = Dog.class.isInstance(dog);

三、反射的基本用法:

  1. 调用方法Object 返回值 = method.invoke(对象, 参数值列表)
    相当于:对象.method(参数值列表)
    如:
Person xiaoming  = new Person();
Class c = xiaoming.getClass();
//Method m = c.getMethod("print", new Class[]{int.class, int.class});
//m.invoke(xiaoming, new int[]{1,2});
Method m = c.getMethod("print", int.class, int.class);
m.invoke(xiaoming, 1,2);

唯一确定某个方法的因素:方法名称 + 方法参数列表

  1. 修改属性Field.set(对象, 要修改的field值)
    相当于:对象属性赋值操作
    如:
Field field = teacher.getClass().getDeclaredField("name");//获取teacher对象的name属性
field.setAccessible(true);//无视field的访问权限问题
field.set(teacher, "小明老师");

四、关于集合的反射

  • 反射都是在编译完之后的操作
  • 编译之后,有着泛型的集合类型,将去泛型化。【换句话说,Java集合类的泛型,是为了防止错误输入而设定的,只在编译时有效】
  • 通过反射,可以绕过编译,这样一来,比如: 在ArrayList<String> list上执行add(100);添加一个整型,则不会报错。【但是这样做,就不能使用for:each来遍历集合】
List<String> list = new ArrayList<>();
list.add("hello");///添加元素“hello”
try {
    Method methodAdd = list.getClass().getMethod("add", Object.class);
    methodAdd.invoke(list,1);///添加元素1
} catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
    e.printStackTrace();
} 
System.out.println(list.toString());
///以下遍历报错:java.lang.ClassCastException
///for (String item:list){
///    System.out.println(item);
///}

五、Java反射相关的异常

  • ClassNotFoundException:未在命名空间内找到指定类。(类名错误,或者类不存在)
  • SecurityException:修改了不允许修改的Accessible标志时
  • NoSuchMethodException:找不到特定方法
  • NoSuchFieldException:找不到特定属性
  • IllegalArgumentException:向方法传递了一个不合法或不正确的参数
  • InstantiationException:程序视图使用Class类中的newInstance方法(此方法本身不能应用于基本类型)创建一个类的实例,而指定的类对象无法被实例化时。【如:实例化抽象类或接口,或者视图创建数组类的实例】
  • IllegalAccessException:当我的程序代码想要通过反射去创建一个实例(非数组)、设置或获取一个字段,或者调用一个方法,但是当前正在执行的方法无法访问指定类、字段、方法或构造函数的定义时,抛出的异常。

相关文章

  • Java--Class类相关与反射重温

    一、注意点 面向对象的世界中,万事万物皆对象。 Java中的类,是java.util.Class类的实例对象 类的...

  • 反射相关类

    1.获取Class类型的对象 Class类封装一个对象和接口运行时的状态,当装载类时,Class类型的对象自动创建...

  • 反射

    一、与反射相关的类 - Class:表示类; - Field:表示成员变量; - Method:表示方法; - C...

  • JAVA 反射机制-学习复盘

    与Java反射相关的类如下: 类名 用途Class类 代表类的实体,在运行的Java应用程序中表示类和接口Fi...

  • Java基础:反射

    反射注解动态代理相关阅读 Java基础:类加载器 Java基础:反射 Java基础:注解 Java基础:动态代理 ...

  • Java 反射机制 (转)

    目录反射机制是什么反射机制能做什么反射机制的相关API通过一个对象获得完整的包名和类名实例化Class类对象获取一...

  • Java反射机制

    反射 java反射是指在程序运行时获取已知名称的类或已有对象相关信息的一种机制,包括类的方法,属性,父类等信息,还...

  • Android反射机制

    Android反射相关知识汇总 一、什么是反射机制? JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这...

  • 一周岁前做好两件事,孩子就不会语言迟缓,保证口齿伶俐

    与语言发展相关的原始反射有四个:张口反射、足跖反射、抓握反射和手拉反射,每个反射的发生、发展和整合都是次第进行的,...

  • 反射

    Class类与Java反射 通过反射可访问的主要描述信息 访问构造方法 Constructor类的常用方法 Mod...

网友评论

    本文标题:Java--Class类相关与反射重温

    本文链接:https://www.haomeiwen.com/subject/mlwuuttx.html