博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【Java反射】Java 泛型基础
阅读量:6836 次
发布时间:2019-06-26

本文共 4011 字,大约阅读时间需要 13 分钟。

笔记来源:

Java Reflect

综述

  • Class类的使用
  • 方法的反射
  • 成员变量的反射
  • 构造函数的反射
  • 类加载机制

Class 类的使用

在面向对象的世界里,万事万物皆对象。

  • 但在Java里面有两样东西不是对象:静态的成员、普通数据类型类(但它们有封装类弥补)
  • 类是对象,类是 java.lang.Class 的实例对象(There is a class named Class)
package com.gcusky.reflect;class ClassDemo {    Foo foo = new Foo(); // Foo的实例对象    /**     * foo 是 Foo 类的实例对象     * Foo 是 Class 类的实例对象,又叫类类型(class type)     */    // 表示1 -> 任何一个类都有一个隐含的静态成员变量class    Class c1 = Foo.class;    // 表示2 -> 已知该类对象可用getClass方法获取类类型    Class c2 = foo.getClass();    // 表示3 -> 用类的全称获取    try {        Class c3 = Class.forName("com.gcusky.reflect.Foo");    } catch (ClassNotFoundException e) {        e.printStackTrace();    }    // 可以通过类的类类型创建该类的实例对象    try {        Foo foo1 = (Foo)c1.newInstance();    } catch (InstantiationException e) {        e.printStackTrace();    } catch (IllegalAccessException e) {        e.printStackTrace();    }}class Foo

Java 动态加载类

Class.forName("类的全称")

  • 不仅表示了类的类类型,还代表了动态加载类

    • 编译时刻加载类是静态加载类
    • 运行时刻加载类是动态加载类
class Office {    public static void main(String[] args) {        // new 创建对象,是静态加载类,在编译时就需要加载所有可能使用到的类        if("Word".equals(args[0])) {            Word w = new Word();            w.start();        }        // Class.forName 创建对象,是动态加载类,在运行时才加载        try {            Class c = Class.forName(args[0])            Word w = (Word) c.newInstance(); // 通过类类型,创建该对象            w.start();        } catch (Exception e) {            e.printStackTrace();        }    }}

Java 获取方法信息

  • 基本的数据类型,void 关键字都存在类类型
  • java.lang.reflect.Method 封装了关于方法的操作
package com.gcusky.reflect;import java.lang.reflect.Method;public class Demo {    /**     * 打印类的信息,包括类的成员函数、成员变量     * @param obj 对象     */    public static void printClassMessage(Object obj) {        // 要获取类的信息,首先要获取类的类类型        Class c = obj.getClass();        // 获取类的全名        String fullName = c.getName();        /**         * Method类:方法对象         * 一个成员方法就是一个Method对象         * getMethods()方法获取的是所有的public的函数,包括父类继承而来的         * getDeclaredMethods() 获取的是所有该类自己声明的方法,不问访问权限         */        Method[] ms = c.getMethods(); // c.getDeclaredMethods();        for (int i = 0; i < ms.length; i++) {            // 得到方法的返回类型            Class returnType = ms[i].getReturnType();            // 得到方法的名称            String name = ms[i].getName();            // 获取参数类型            Class[] paramTypes = ms[i].getParameterTypes();        }    }}

Java 获取成员变量信息

  • 成员变量也是对象
  • java.lang.reflect.Field 封装了关于成员变量的操作
/**         * 成员变量也是对象,Field封装了关于成员变量的操作         * getFields()获取的是所有的public的成员变量         * getDeclaredMethods()获取的是所有该类自己声明的成员变量         */        Field[] fs = c.getDeclaredFields(); // c.getFields();        for (int i = 0; i < fs.length; i++) {            // 得到成员变量的类型            Class fieldType = fs[i].getType();            String typeName = fieldType.getName();            // 得到成员变量的名称            String fieldName = fs[i].getName();        }

Java 获取构造函数信息

/**         * 构造函数也是对象         * java.lang.Constructor中封装了构造函数的信息         */        Constructor[] cs = c.getDeclaredConstructors();        for (Constructor constructor : cs) {            constructor.getName();            Class[] paramType = constructor.getParameterTypes();        }

Java 方法的反射

  1. 如何获取某个方法:方法的名称和方法的参数列表才能唯一决定某个方法
  2. 方法反射的操作:method.invoke(对象, 参数列表)
class A {    public void print(int a, int b) {        System.out.println(a + b);    }}A a = new A();Class c = a.getClass();try {    // Method m = c.getMethod("print", new Class[]{int.class, int.class});    Method m = c.getMethod("print", int.class, int.class);    // Object o = m.invoke(a, new Object[]{10, 20});    Object o = m.invoke(a, 10, 20);} catch (Exception e) {    e.printStackTrace();}

Java 类加载机制

ArrayList list = new ArrayList();ArrayList
list1 = new ArrayList
();list == list1; // truelist1.add(20); // error - 编译检测出错
  • 反射都是编译之后的操作,因此可看出泛型在编译之后会被擦除
  • Java 中集合的泛型用于防止错误输入,只在编译阶段有效,绕过编译则无效
Class c = list1.getclass();try {    Method m = c.getMethod("add", Object.class);    m.invoke(list1, 20); // correct - 绕过编译操作就绕过了泛型} catch (Exception e) {    e.printStackTrace();}

参考资料:

转载地址:http://qkhkl.baihongyu.com/

你可能感兴趣的文章
rabbitmy实战
查看>>
mysql-Mac终端下遇到的问题总结
查看>>
表空间迁移(二)
查看>>
准备mysql函数库和PHP文件
查看>>
初学者应该了解的编程陷阱:javascript篇
查看>>
【安全牛学习笔记】手动漏洞挖掘(三)
查看>>
硬链接和软链接使用,以及区别
查看>>
history的详解与使用
查看>>
随机数
查看>>
【入门须知】学DIV CSS技术如何入门?
查看>>
js中match、replace方法中使用正则表达式
查看>>
Unity3D小功能 小技巧 小教程 小原理(持续更新...)
查看>>
Bullmind在线读书笔记软件
查看>>
#技术分享# “乐高”内核的诞生
查看>>
我的友情链接
查看>>
rtmp的URL里面mp3:和mp4:是啥意思
查看>>
ZooKeeper伪分布式集群安装
查看>>
防火墙 之 iptables 匹配条件讲解
查看>>
Nginx配置文件详细说明
查看>>
Tomcat远程调试
查看>>