先看看通过反射能干嘛

  • 示例:修改对象的private实例变量
package testpack;
import java.lang.reflect.Field;
public class Test1 {
public static void main(String[] args)throws Exception{
Person per=new Person("Java",21);
System.out.println("现在的per对象是:"+per); //[name= Java , age= 21 ] Class<Person> perClazz=Person.class; //获取Person类的Class对象 Field fName=perClazz.getDeclaredField("name"); //获取Person类的名为“name”的变量,即使是private修饰
fName.setAccessible(true); //取消该变量的访问权限检查
fName.set(per, "C++"); //将per对象的name变量改为“C++” Field fAge=perClazz.getDeclaredField("age");
fAge.setAccessible(true);
fAge.set(per, 33); //将per对象的age变量改为“33” System.out.println("private的实例变量被修改了,还是那个per对象:"+per); //[name= C++ , age= 33 ]
}
}
class Person{
private int age;
private String name;
public Person(String n,int a){
name=n;
age=a;
}
public String toString(){
return "[name= "+name+" , age= "+age+" ]";
}
}
  • 上面的示例中,虽然age和name被private修饰,但还是被修改了,那这岂不是很不安全,违背了封装的初衷?我也不知道

java.lang.class

  • 有一个类很特别,它是所有类的类,它就是java.lang.class
  • 要使用一个类的时候,类加载器找到并加载这个类,同时返回其Class对象;也就是说只要一个类被加载了,那么就一定存在它的Class对象
  • 如何获得一个类的Class对象?以String类为例
    • Class.forName("java.lang.String"):用Class类的静态方法forName("包名+类名")来获取
    • String.class:通过调用一个类的class属性来获取
      • 一般用这种方式
      • 代码更安全。程序在编译阶段就可以检查要访问的Class对象是否存在。?不懂
      • 程序性能更好。因为无须调用方法。
    • String的实例.getClass():通过Object类的一个实例方法getClass()方法获取
  • 获取一个类的Class对象后,就可以调用其方法获得该对象和该类的真实信息了

Class主要方法

  • 构造器:以下用“para”代表Class<?>...parameterTypes,这是个数可变的形参列表

    • Constructor getConstructor(para):返回该Class对象对应类的、带指定形参的public构造器
    • Constructor<?>[] getConstructors():返回对应类的所有public构造器
    • Constructor getDeclaredConstructor(para):返回对应类的、带指定形参列表的构造器,不论是什么访问权限
    • Constructor<?>[] getDeclaredConstructors():返回对应类的所有构造器,不论访问权限
  • 方法:
    • Method getMethod(String name,para):返回对应类的、指定方法名、指定形参列表的public方法
    • Method[] getMethods():返回指定类的所有public方法
    • Method getDeclaredMethod(String name,para):返回对应类的、指定方法名、指定形参列表的方法,不论访问权限
    • Method[] getDeclaredMethods():返回对应类的所有方法,不论访问权限
  • 成员变量
    • Field getField(String name):返回对应类的、指定名称的public成员变量
    • Filed[] getFields():返回对应类的所有public成员变量
    • Field getDeclaredField(String name):返回对应类的、指定名称的成员变量,不论访问权限
    • Field[] getDeclaredFields():返回对应类的所有成员变量,不论访问权限
  • 注解
    • <A extends Annotation> A getAnnotation(Class<A>AnnotationClass):获取对应类的指定的注解,不存在则返回null
    • <A extends Annotation> A getDeclaredAnnotation(Class<A>AnnotationClass):获取直接修饰该对应类的、指定的注解,不存在则返回null
    • Annotation[] getAnnotations():返回对应类上的所有注解
    • Annotation[] getDeclaredAnnotations():返回直接修饰该对应类的所有注解
    • <A extends Annotation> A[] getAnnotationsByType(Class<A>AnnotationClass):针对重复注解功能,返回修饰该对应类的、指定类型的多个注解
    • <A extends Annotation> A[] getDeclaredAnnotationsByType(Class<A>AnnotationClass):针对重复注解功能,获取直接修饰对应类的、指定类型的注解
  • 内部类
    • Class<?>[] getDeclaredClasses():返回对应类里包含所有内部类
  • 外部类:
    • Class<?> getDeclaringClass():返回对应类的所在的外部类
  • 接口:
    • Class<?> getInterfaces():返回对应类所实现的所有接口
  • 父类:
    • Class<?super T> getSuperclass():返回对应来的父类的Class对象
  • 修饰符:
    • int getModifiers():返回对应类或接口的所有修饰符对应的常量,应使用Modifier工具类的方法解码,才能获得真实的修饰符
  • 所在包:
    • Package getPackage():获取对应类所在的包
  • 类名:
    • String getName():返回对应类的名称,全局限定名(即包含包名)
    • String getSimpleName():返回对应类的名称,不包含包名的类名
  • is方法
    • boolean isAnnotation:是不是注解类型
    • boolean isAnnotationPresent(Class<? extends Annotation> annotationClass):对应类是否使用了Annotation修饰
    • boolean isAnonymousClass():对应类是否是一个匿名类
    • boolean isArray():对应类是否是一个数组
    • boolean isEnum():对应类是否是一个枚举
    • boolean isInterface():对应类是否是一个接口
    • boolean isInstance(Object obj):判断该obj是不是对应类的实例,可以完全替代instanceof
  • 相关方法示例:以Strin类为例
package testpack;

import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method; public class Test1 {
public static void main(String[] args)throws Exception{
Class clazz=String.class; System.out.println("---------------------------------下面是String的成员变量部分---------------------------------");
System.out.println("-----------所有的public成员变量-----------");
Field[] pfs=clazz.getFields();
for (Field f:pfs) {
System.out.println(f);
}
System.out.println("-----------所有成员变量-----------");
Field[] fs=clazz.getDeclaredFields();
for (Field f:fs) {
System.out.println(f);
} System.out.println("---------------------------------下面是String的构造器部分---------------------------------");
System.out.println("String的无参构造:"+clazz.getConstructor(null));
System.out.println("String以byte[]为参数的构造器:"+clazz.getConstructor(byte[].class));
System.out.println("String以StringBuffer为参数的构造器:"+clazz.getConstructor(StringBuffer.class));
System.out.println("---------------所有构造器-----------------");
Constructor[] cs=clazz.getDeclaredConstructors();
for(Constructor c:cs){
System.out.println(c);
} System.out.println("---------------------------------下面是String的方法部分---------------------------------");
System.out.println("String的名为intern的无参方法:"+clazz.getMethod("intern",null));
System.out.println("String的名为valueOf的参数为int的方法:"+clazz.getMethod("valueOf",int.class));
System.out.println("--------------所有方法--------------------");
Method[] ms=clazz.getDeclaredMethods();
for (Method m:ms) {
System.out.println(m);
}
System.out.println(); System.out.println("---------------------------------下面是String的注解部分---------------------------------");
System.out.println("---------下面是String的所有注解---------------");
Annotation[] as=clazz.getAnnotations();
for (Annotation a:as) {
System.out.println(a); //没有输出:因为String类没有注解(但String类内部的一些元素有注解)
}
System.out.println("---------------------------------下面是String的所有内部类---------------------------------");
Class[] css=clazz.getDeclaredClasses();
for (Class c:css) {
System.out.println(c);
}
System.out.println("---------------------------------下面是String实现的所有接口---------------------------------");
Class[] is=clazz.getInterfaces();
for (Class i:is) {
System.out.println(i);
}
System.out.println("---------------------------------其他---------------------------------");
System.out.println("String的直接父类:"+clazz.getSuperclass());
System.out.println("String的修饰符:"+clazz.getModifiers());
System.out.println("String所在的包:"+clazz.getPackage());
System.out.println("String的全局限定名:"+clazz.getName());
System.out.println("String的类名:"+clazz.getSimpleName());
}
}

关于参数的反射:since1.8

  • 构造方法和方法中包含形参列表,Java1.8增加了Parameter类来描述参数
  • 上面Class对象关于构造器和方法的返回值分别是:Constructor和Method,这两个类是Executable类的子类
  • Executable的主要方法有:
    • boolean isVarArgs():是否包含可变数量的形参
    • int getModifiers():获取修饰符
    • int getParameterCount():获取形参数量
    • Parameter[] getParameters():获取所有形参
  • Parameter的主要方法
    • int getModifiers():获取形参的修饰符
    • String getName():获取形参名
    • Type getParameterizedType():获取带泛型的形参类型
    • Class<?> getType():获取形参类型
    • boolean isNamePresent():所在类的class文件中是否包含了形参名信息;
      • 一般情况下,编译的时候都不包含形参名,除非加上“-parameters”选项
    • boolean isVarArgs():该参数是否为个数可变的形参
  • 见示例:
package testpack;

import java.lang.reflect.Constructor;
import java.lang.reflect.Parameter; public class Test1 {
public static void main(String[] args)throws Exception{
Class clazz=String.class;
Constructor c=clazz.getConstructor(byte[].class,int.class,int.class);
System.out.println("该构造器的形参个数:"+c.getParameterCount());
Parameter[] ps=c.getParameters();
for (Parameter p:ps) {
System.out.println("该参数是:"+p);
System.out.println("该参数的修饰符:"+p.getModifiers());
System.out.println("该参数的形参名:"+p.getName());
System.out.println("形参类型:"+p.getType());
System.out.println("是否有形参名信息:"+p.isNamePresent());
System.out.println("是否是个数可变的形参:"+p.isVarArgs());
System.out.println("--------------------------");
}
}
}

0033 Java学习笔记-反射-初步1的更多相关文章

  1. 0034 Java学习笔记-反射-初步2-操作对象

    通过反射创建对象 通过反射创建对象有两种方式,一种通过Class对象的newInstance()方法,一种是获取到Class对象的Constructor后,再调用newInstance()方法,前者要 ...

  2. Java学习笔记--反射

    什么是Java反射 概念 java反射是指java能够在运行时确定类的类型信息,包括其方法.字段.构造函数等,并能够通过反射调用类或者类对象的方法.在Java中,java.lang.Class类与ja ...

  3. Java学习笔记--反射API

    反射API 1.反射API的介绍 通过反射API可以获取Java程序在运行时刻的内部结构.比如Java类中包含的构造方法.域和方法等元素,并可以与这些元素进行交换.     按照 一般地面向对象的设计 ...

  4. Java 学习笔记 反射与迭代器

    反射 使用反射获得类 Class cls = Class.forName("全类名") //包括包名 Class cls = xx.Class;//xx代表类名 使用反射获得构造方 ...

  5. JAVA 学习笔记 - 反射机制

    1.   JAVA反射机制的概念 2. 怎样实例化一个 Class对象 Class.forName(包名.类名); 对象.getClass(); 类.class; ================== ...

  6. Java学习笔记——反射

    反射就是把Java类中的各种成分映射成相应的java类. Class类-->java程序中的各个java类属于同一事物,描述这类事物的Java类名就是Class. Class.forName的作 ...

  7. Java学习笔记-反射机制

    Java反射机制实在运行状态时,对于任意一个类,都能够知道这个类的属性和方法,对于任意一个对象,都能够调用他的任意一个属性和方法 获取Class对象的三种方式 Object类中的getClass()方 ...

  8. 0035 Java学习笔记-注解

    什么是注解 注解可以看作类的第6大要素(成员变量.构造器.方法.代码块.内部类) 注解有点像修饰符,可以修饰一些程序要素:类.接口.变量.方法.局部变量等等 注解要和对应的配套工具(APT:Annot ...

  9. 0032 Java学习笔记-类加载机制-初步

    JVM虚拟机 Java虚拟机有自己完善的硬件架构(处理器.堆栈.寄存器等)和指令系统 Java虚拟机是一种能运行Java bytecode的虚拟机 JVM并非专属于Java语言,只要生成的编译文件能匹 ...

随机推荐

  1. 读取xml数据装配到字典中之应用场景

    前段时间看到支付宝设置里面有个多语言这个功能,蛮有意思的,就想双休没事的话做个相关的demo玩玩,可是礼拜六被妹子拽出去玩了一天,来大上海有大半年了,基本没有出去玩过,妹子说我是超级宅男,也不带她出去 ...

  2. TCP同步与异步,长连接与短连接【转载】

    原文地址:TCP同步与异步,长连接与短连接作者:1984346023 [转载说明:http://zjj1211.blog.51cto.com/1812544/373896   这是今天看到的一篇讲到T ...

  3. 解析大型.NET ERP系统 单据标准(新增,修改,删除,复制,打印)功能程序设计

    ERP系统的单据具备标准的功能,这里的单据可翻译为Bill,Document,Entry,具备相似的工具条操作界面.通过设计可复用的基类,子类只需要继承基类窗体即可完成单据功能的程序设计.先看标准的销 ...

  4. 07.GitHub实战系列~7.Git之VS2013团队开发(如果不想了解git命令直接学这篇即可)

    GitHub实战系列汇总:http://www.cnblogs.com/dunitian/p/5038719.html ———————————————————————————————————————— ...

  5. JS事件调试 - 查找HTML元素绑定的事件以及绑定代码所在位置

    日常的网页开发调试工作中,经常需要知道指定的某个网页元素绑定了哪些事件以及绑定代码的位置,下面介绍三种用来跟踪页面中的事件的方法. 1.使用firefox调试 我们可以使用firefox的debug工 ...

  6. Android混合开发之WebView使用总结

    前言: 今天修改项目中一个有关WebView使用的bug,激起了我总结WebView的动机,今天抽空做个总结. 混合开发相关博客: Android混合开发之WebView使用总结 Android混合开 ...

  7. Javascript之自定义事件

    Javascript自定义事件,其本质就是观察者模式(又称订阅/发布模式),它的好处就是将绑定事件和触发事件相互隔离开,并且可以动态的添加.删除事件. 下面通过实例,一步一步构建一个具体的Javasc ...

  8. JMS学习之路(一):整合activeMQ到SpringMVC

    JMS的全称是Java Message Service,即Java消息服务.它主要用于在生产者和消费者之间进行消息传递,生产者负责产生消息,而消费者负责接收消息.把它应用到实际的业务需求中的话我们可以 ...

  9. webService学习之路(二):springMVC集成CXF快速发布webService

    继上一篇webService入门之后,http://www.cnblogs.com/xiaochangwei/p/4969448.html ,现在我将我周六在家研究的结果公布出来 本次集成是基于之前已 ...

  10. jQuery的DOM操作实例(3)——创建节点&&编写一个弹窗

    一.原生JavaScript编写弹窗 二.jQuery编写弹窗 知识点归纳总结: 在原生JavaScript中,创建一个节点: var oDiv=document.createElement(&quo ...