java 的反射机制
一:介绍
1.大纲
#1
允许程序在执行期间,调用反射API取得任何类的内部信息,并且可以直接操作任何对象的内部属性和方法。
#2
学习反射,需要掌握的知识点:
*实例化class类
*获取类的完整结构
*通过反射调用类的属性和方法
*动态代理
2.涉及到的一些API
java.lang.Class 类
java.lang.reflect.Field 属性
java.lang.reflect.Method 方法
java.lang.reflect.Constructor 构造器
二:简单反射的小示例(可以直接看后面的内容)
1.新建要反射的类Person
这个要被反射的类中不含有父类,接口,注解等额外的部分,只是一个特别简单的可以被用来反射的类,用来做演示。
package demo2;
public class Person1 {
//这里为了说明反射,权限为public
public String name;
//这里为了说明反射,做对比,权限为private
private int age; public Person1() {
super();
}
public Person1(String name) {
super();
this.name = name;
}
public Person1(int age) {
super();
this.age = age;
}
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;
}
@Override
public String toString() {
return "Person1 [name=" + name + ", age=" + age + "]";
}
//两个普通的方法
//不带参数的函数
public void show(){
System.out.println("this is person class");
}
//带参数的函数
public void diaplay(String nation){
System.out.println("contry is "+nation);
} }
2.反射的测试
这个部分包括建立反射源
通过反射设置属性
通过反射调用方法函数
package demo2; import java.lang.reflect.Field;
import java.lang.reflect.Method; public class Test1 { public static void main(String[] args)throws Exception {
reflectMethod();
}
public static void reflectMethod()throws Exception{
//产生对应的类
Class clazz=Person1.class;
Person1 p=(Person1)clazz.newInstance();
System.out.println(p);
System.out.println("-------------------------"); //设置public权限的属性
Field f=clazz.getField("name");
f.set(p, "zhangsan");
System.out.println(p);
System.out.println("-------------------------"); //设置private权限的属性
Field f1=clazz.getDeclaredField("age");
f1.setAccessible(true);//增加访问权限
f1.set(p, 90);
System.out.println(p);
System.out.println("-------------------------"); //调用不带参数的函数方法
Method m=clazz.getMethod("show");
m.invoke(p);
System.out.println("-------------------------"); //调用带参数的函数方法
Method m1=clazz.getMethod("diaplay",String.class);
m1.invoke(p, "China");
}
}
3.运行结果
-----------------------------------------------------------------------------------------------#反射重点#---------------------------------------------------------------------------------------------------
三:实现Class类的四种实现方式(所有反射的基础源头---class类的获取)
1.介绍四种方式获取要反射类的class文件
*用运行时类本身的.class获取
*通过运行时类的对象的获取
*以class的静态方法获取
*通过类的加载器获取
2.程序
package demo2; import org.junit.Test; public class Test2 {
@Test
public void classMethod() throws ClassNotFoundException{
//通过类的class文件
Class c1=Person1.class;
System.out.println(c1); //通过运行时类的对象获取class文件
Person1 p=new Person1();
Class c2=p.getClass();
System.out.println(c2); //通过class的静态方法
String name="demo2.Person1";
Class c3=Class.forName(name);
System.out.println(c3); //通过类的加载器获得class
ClassLoader classLoader=this.getClass().getClassLoader();
Class c4=classLoader.loadClass(name);
System.out.println(c4);
} }
3.运行结果
结果看到:四种方式都可以获得class类。
四:类的加载器(解释一下上面方式四中类的加载器,次要内容)
1.介绍
2.程序验证
package demo2;
import org.junit.Test;
public class Test3 {
@Test
public void show(){
//systemClassLoader
ClassLoader c1=ClassLoader.getSystemClassLoader();
System.out.println(c1); //ExterSionClassLoader
ClassLoader c2=c1.getParent();
System.out.println(c2); //null(这一个类加载器不会被获取)
ClassLoader c3=c2.getParent();
System.out.println(c3); }
}
3.运行结果
4.在方式四种使用的是哪一个加载器(程序验证)
package demo2;
import org.junit.Test;
public class Test4 {
@Test
public void method(){
String name="demo2.Person1";
ClassLoader classLoader=this.getClass().getClassLoader();
System.out.println(classLoader);
}
}
5.运行结果
五:创建运行时类对象(class文件的基础上)
1.要求
要反射的类中有空参的构造器(最好是这样)
构造器的权限为public
2.程序实现解释
package demo2;
public class Test5 {
public static void main(String[] args)throws Exception {
Class c=Person1.class;
Object obj=c.newInstance();
Person1 p=(Person1)obj;
System.out.println(p);
}
}
3.运行结果
六:重新构建复杂的即将被反射的类
1.构建复杂的类对象
包含:
*父类
*多接口
*注解
*内部类
*异常
首先是父类:
package com.at.java; public class Creature<T>{
public double weight;
public void breath(){
System.out.println("呼吸");
}
}
自定义接口:
package com.at.java; import java.io.Serializable;
public interface MyInterface extends Serializable{ }
自定义注解:
package com.at.java;
import static java.lang.annotation.ElementType.CONSTRUCTOR;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.LOCAL_VARIABLE;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.ElementType.TYPE;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; @Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
String value();
}
反射的类:
package com.at.java; @MyAnnotation(value = "atguigu")
public class Person extends Creature<String> implements Comparable,MyInterface{
public String name;
private int age;
int id;
public Person() {
super();
}
public Person(String name) {
super();
this.name = name;
}
private Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
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;
} public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@MyAnnotation(value = "abc123")
public void show(){
System.out.println("this is person");
} private Integer display(String nation,Integer i) throws Exception{
System.out.println("国籍:" + nation);
return i;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
@Override
public int compareTo(Object o) {
// TODO Auto-generated method stub
return 0;
} public static void info(){
System.out.println("信息");
} class Bird{ } }
七:获取以及调用类的属性
包括:
*所有属性的获取
*指定属性的调用
1.获取对应类运行时的属性
包括两种;
*getFields():只能获取到运行时类中及其父类中声明为public的属性
*getDeclaredFields():获取运行时类本身声明的所有的属性
package com.at.java;
import java.lang.reflect.Field;
public class Test1 {
public static void main(String[] args){
get1();
System.out.println("###################");
get2();
}
/**
* getFields():只能获取到运行时类中及其父类中声明为public的属性
*/
public static void get1(){
Class clazz=Person.class;
Field[] f=clazz.getFields();
for(int i=0;i<f.length;i++){
System.out.println(f[i].getName());
}
}
/**
* getDeclaredFields():获取运行时类本身声明的所有的属性
*/
public static void get2(){
Class clazz=Person.class;
Field[] f=clazz.getDeclaredFields();
for(Field ff:f){
System.out.println(ff.getName());
}
}
}
2.运行结果
使用###进行将两种方式进行隔离。
3.获取对应类运行时的属性的各个部分的内容
主要包括:
*权限
*变量名
*变量名
package com.at.java; import java.lang.reflect.Field;
import java.lang.reflect.Modifier; public class Test2 { public static void main(String[] args) {
get2(); }
/**
* getDeclaredFields():获取运行时类本身声明的所有的属性的各个部分
*/
public static void get2(){
Class clazz=Person.class;
Field[] f=clazz.getDeclaredFields();
for(Field ff:f){
//属性权限
int num=ff.getModifiers();
String str=Modifier.toString(num);
System.out.print(str+"\t"); //属性类型
Class type=ff.getType();
System.out.print(type.getName()+"\t"); //属性变量名
System.out.println(ff.getName());
}
} }
4.运行结果
5.调用设置指定属性
注意点事权限问题
package com.at.java; import java.lang.reflect.Field; public class Test6 {
public static void main(String[] args)throws Exception {
Class clazz=Person.class;
/**
* 属性权限为public
*/
Field name = clazz.getField("name");
Person p = (Person)clazz.newInstance();
//将运行时类的指定的属性赋值
name.set(p,"Jerry");
System.out.println(p);
//将运行时类的指定的属性赋值后再取出
System.out.println("name="+name.get(p)); System.out.println("########################");
/**
* 属性权限为private
*/
Field age = clazz.getDeclaredField("age");
age.setAccessible(true);//由于属性权限修饰符的限制,需要在操作前使得此属性可被操作。
age.set(p,10);
System.out.println(p); System.out.println("#######################");
/**
* 属性的权限为默认default
* 这个set时不需要setAccessible(true)。
*/
Field id = clazz.getDeclaredField("id");
id.set(p,3);
System.out.println(p);
}
}
6.运行结果
八:获取与调用对应类运行时的方法
包括两种:
*获取所有方法
*调用指定方法
1.获取对应类运行时的方法
包括两种:
*getMethods():获取运行时类及其父类中所有的声明为public的方法
*getDeclaredMethods():获取运行时类本身声明的所有的方法
package com.at.java;
import java.lang.reflect.Method;
public class Test3 {
public static void main(String[] args) {
get1();
System.out.println("#############");
get2();
}
/**
* getMethods():获取运行时类及其父类中所有的声明为public的方法
*/
public static void get1(){
Class clazz=Person.class;
Method[] m=clazz.getMethods();
for(Method mm: m){
System.out.println(mm.getName());
}
}
/**
* getDeclaredMethods():获取运行时类本身声明的所有的方法
*/
public static void get2(){
Class clazz=Person.class;
Method[] m=clazz.getDeclaredMethods();
for(Method mm:m){
System.out.println(mm.getName());
}
}
}
2.运行结果
3.获取对应类运行时的方法的各个部分
包括:
*注解
*权限
*返回类型
*方法名
*参数列表
*异常类型
package com.at.java; import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier; public class Test4 { public static void main(String[] args) {
get2();
}
/**
* 注解 权限修饰符 返回值类型 方法名 形参列表 异常
*/
public static void get2(){
Class clazz = Person.class;
Method[] m2 = clazz.getDeclaredMethods();
for(Method m : m2){
//1.注解
Annotation[] ann = m.getAnnotations();
for(Annotation a : ann){
System.out.println(a);
} //2.权限修饰符
String str = Modifier.toString(m.getModifiers());
System.out.print(str + " "); //3.返回值类型
Class returnType = m.getReturnType();
System.out.print(returnType.getName() + " "); //4.方法名
System.out.print(m.getName() + " "); //5.形参列表
System.out.print("(");
Class[] params = m.getParameterTypes();
for(int i = 0;i < params.length;i++){
System.out.print(params[i].getName() + " args-" + i + " ");
}
System.out.print(")"); //6.异常类型
Class[] exps = m.getExceptionTypes();
if(exps.length != 0){
System.out.print("throws ");
}
for(int i = 0;i < exps.length;i++){
System.out.print(exps[i].getName() + " ");
}
System.out.println();
}
}
}
4.运行结果
5.调用指定方法
package com.at.java;
import java.lang.reflect.Method;
public class Test7 {
public static void main(String[] args) throws Exception{
Class clazz = Person.class;
Person p = (Person)clazz.newInstance();
/**
* public
*/
Method m1 = clazz.getMethod("show");
Object returnVal = m1.invoke(p);
System.out.println(returnVal); //因为返回值为void,所以打印为null Method m2 = clazz.getMethod("toString");
Object returnVal1 = m2.invoke(p); //因为返回值为string,所以这样调用不会有什么现象
System.out.println(returnVal1); //没有现象,所以打印就是打印返回值 /**
* private
* 同时,这是带参数的函数
*/
Method m4 = clazz.getDeclaredMethod("display",String.class,Integer.class);
m4.setAccessible(true);
Object value = m4.invoke(p,"CHN",10);
System.out.println(value); /**
* static 方法,单独提出来
*/
Method m3 = clazz.getMethod("info");
m3.invoke(Person.class);
}
}
6.运行结果
九:获取构造器
包括:
*所有的构造器
*调用指定的构造器
1.获取所有的构造器
package com.at.java;
import java.lang.reflect.Constructor;
public class Test8 {
public static void main(String[] args) throws Exception{
String className = "com.at.java.Person";
Class clazz = Class.forName(className);
/**
* 获取所有的构造器
*/
Constructor[] cons = clazz.getDeclaredConstructors();
for(Constructor c : cons){
System.out.println(c);
}
}
}
2.运行结果
3.调用指定的构造器
package com.at.java;
import java.lang.reflect.Constructor;
public class Test9 {
public static void main(String[] args)throws Exception{
String className = "com.at.java.Person";
Class clazz = Class.forName(className);
/**
* 调用String,int的构造器
*/
Constructor cons = clazz.getDeclaredConstructor(String.class,int.class);
cons.setAccessible(true);
Person p = (Person)cons.newInstance("罗伟",20);
System.out.println(p);
}
}
4.运行结果
十:获取其他的内容(父类,接口,注解,包,)
1.程序
package com.at.java;
import java.lang.annotation.Annotation;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import org.junit.Test; public class Test10 {
//6.获取注解
@Test
public void test6(){
Class clazz = Person.class;
Annotation[] anns = clazz.getAnnotations();
for(Annotation a : anns){
System.out.println(a);
}
} //5.获取所在的包
@Test
public void test5(){
Class clazz = Person.class;
Package pack = clazz.getPackage();
System.out.println(pack);
} //4.获取实现的接口
@Test
public void test4(){
Class clazz = Person.class;
Class[] interfaces = clazz.getInterfaces();
for(Class i : interfaces){
System.out.println(i);
}
} //3*.获取父类的泛型
@Test
public void test3(){
Class clazz = Person.class;
Type type1 = clazz.getGenericSuperclass(); ParameterizedType param = (ParameterizedType)type1;
Type[] ars = param.getActualTypeArguments(); System.out.println(((Class)ars[0]).getName());
} //2.获取带泛型的父类
@Test
public void test2(){
Class clazz = Person.class;
Type type1 = clazz.getGenericSuperclass();
System.out.println(type1);
} //1.获取运行时类的父类
@Test
public void test1(){
Class clazz = Person.class;
Class superClass = clazz.getSuperclass();
System.out.println(superClass);
}
}
2.运行结果
十一:动态代理
1.静态代理
/**
* 静态代理模式
*/
package com.at.java1;
//接口
interface ClothFactory{
void productCloth();
} //被代理类
class NikeClothFactory implements ClothFactory{
@Override
public void productCloth() {
System.out.println("Nike");
}
public void productCloth2() {
System.out.println("Nike2");
}
} //代理类
class ProxyFactory implements ClothFactory{
//引用
ClothFactory cf;
public ProxyFactory(ClothFactory cf){ //创建代理类的对象时,实际传入一个被代理类的对象
this.cf = cf;
} @Override
public void productCloth() {
System.out.println("一共$1000");
cf.productCloth(); //实际在代理类中执行的还是被代理类的方法
} } public class TestClothProduct {
public static void main(String[] args) {
NikeClothFactory nike = new NikeClothFactory();
ProxyFactory proxy = new ProxyFactory(nike); //将被代理类传入代理类中
proxy.productCloth();
}
}
2.运行结果
3.动态代理
/**
* 动态代理
*/
package com.at.java1;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
//接口
interface Subject {
void action();
}
//被代理类
class RealSubject implements Subject {
public void action() {
System.out.println("我是被代理类,记得要执行我哦!");
}
} //代理类
//动态代理都要实现接口InvocationHandler
class MyInvocationHandler implements InvocationHandler {
Object obj;
//①给被代理的对象实例化②返回一个代理类的对象
public Object blind(Object obj) {
this.obj = obj;
return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj
.getClass().getInterfaces(), this);
} //当通过代理类的对象发起对被重写的方法的调用时,都会转换为对如下的invoke方法的调用
@Override
public Object invoke(Object proxy, Method method, Object[] args)throws Throwable {
Object returnVal = method.invoke(obj, args);
return returnVal;
}
} public class TestProxy {
public static void main(String[] args) {
RealSubject real = new RealSubject();
MyInvocationHandler handler = new MyInvocationHandler();
//动态的返回一个同样实现了real所在类实现的接口Subject的代理类的对象。
Object obj = handler.blind(real);
Subject sub = (Subject)obj;
sub.action();
}
}
4.运行结果
十二:动态代理与静态代理的区别
2017.12.21,今天查看了一下他们之间的区别,在这篇文章中解释的挺好的,就没有重新整理,直接粘贴一下链接。
http://blog.csdn.net/hejingyuan6/article/details/36203505。
在这篇文章中,这一段比我上面的程序写的更好理解:
java 的反射机制的更多相关文章
- Java 类反射机制分析
Java 类反射机制分析 一.反射的概念及在Java中的类反射 反射主要是指程序可以访问.检测和修改它本身状态或行为的一种能力.在计算机科学领域,反射是一类应用,它们能够自描述和自控制.这类应用通过某 ...
- java的反射机制
一.java的反射机制浅谈 最近研究java研究得很给力,主要以看博文为学习方式.以下是我对java的反射机制所产生的一些感悟,希望各位童鞋看到失误之处不吝指出.受到各位指教之处,如若让小生好好感动, ...
- Java中反射机制和Class.forName、实例对象.class(属性)、实例对象getClass()的区别
一.Java的反射机制 每个Java程序执行前都必须经过编译.加载.连接.和初始化这几个阶段,后三个阶段如下图: 其中
- java笔记--反射机制之基础总结与详解
一.反射之实例化Class类的5种方式: java的数据类型可以分为两类,即引用类型和原始类型(即基本数据类型). 对于每种类型的对象,java虚拟机会实例化不可变的java.lang.Class对象 ...
- JAVA的反射机制学习笔记(二)
上次写JAVA的反射机制学习笔记(一)的时候,还是7月22号,这些天就瞎忙活了.自己的步伐全然被打乱了~不能继续被动下去.得又一次找到自己的节奏. 4.获取类的Constructor 通过反射机制得到 ...
- java笔录---反射机制(1)
引言 为了方便记忆java的反射机制,在这里仔细的总结了一下.主要是怕以后忘记了,这样也方便回忆.因为最近利用空余时间深入的了解spring和Mybatis框架, 像spring中核心模块IO ...
- Java高新技术 反射机制
Java高新技术 反射机制 知识概要: (1)反射的基石 (2)反射 (3)Constructor类 (4)Field类 (5)Method类 (6)用反射方 ...
- java的反射机制浅谈(转)
原文链接:java的反射机制浅谈 一.java的反射机制浅谈 1.何谓反射机制 根据网文,java中的反射机制可以如此定义: JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性 ...
- 【转】Java利用反射机制访问私有化构造器
Java利用反射机制访问私有化构造器 博客分类: java 我们都知道,当一个类的构造方法被设为私有的时候(private),在其他类中是无法用new来实例化一个对象的. 但是有一种方法可以把带有 ...
- 【转】java原理—反射机制
一.什么是反射:反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问.检测和修改它本身状态或行为的一种能力.这一概念的提出很快引发了计算机科学领域关于应用反射性的研究.它首先被程序语言 ...
随机推荐
- 动态dp 板子
动态dp 瞎扯两句吧 先从序列上理解,维护链的最大独立集. 考虑是从左边转移的,那么矩阵的转移唯一,直接放在线段树上就可以了. 放在树上的话,儿子都可以转移,把轻儿子的转移放在子链链头更新,然后每条链 ...
- python Popen卡死问题
程序经常卡死,定位了半天才定位到原因,原来是Popen导致的卡死: 程序如下: s = subprocess.Popen([*,*,*], stdout=subprocess.PIPE) ret = ...
- Solr记录-solr内核与索引
Solr核心(内核) Solr核心(Core)是Lucene索引的运行实例,包含使用它所需的所有Solr配置文件.我们需要创建一个Solr Core来执行索引和分析等操作. Solr应用程序可以包含一 ...
- 【官方文档】Nginx模块Nginx-Rtmp-Module学习笔记(一) RTMP 命令详解
源码地址:https://github.com/Tinywan/PHP_Experience 说明: rtmp的延迟主要取决于播放器设置,但流式传输软件,流的比特率和网络速度(以及响应时间“ping” ...
- 转自知乎大神----JS 闭包是什么
大名鼎鼎的闭包!这一题终于来了,面试必问. 请用自己的话简述 什么是「闭包」. 「闭包」的作用是什么. --------------------------------------- 首先来简述什么是 ...
- 第9月第12天 lua_push lua_to luaL_check stack quick
1. c代码中通过lua_push 把数据压入堆栈,lua调用c函数得到数据.luaL_check是对lua_to的封装,从堆栈中获取lua代码中函数调用的数据. static int lread(l ...
- Anaconda+django写出第一个web app(六)
今天学习如何写一个注册用户的界面. 上一节的导航栏中我们修改了导航栏右侧的文字为register并将路径设置为/register,内容如下: <li><a href="/r ...
- 洛谷 P4910 帕秋莉的手环 矩阵乘法+快速幂详解
矩阵快速幂解法: 这是一个类似斐波那契数列的矩乘快速幂,所以推荐大家先做一下下列题目:(会了,差不多就是多倍经验题了) 注:如果你不会矩阵乘法,可以了解一下P3390的题解 P1939 [模板]矩阵加 ...
- objective-c 几何类常用方法整理
CGGeometry参考定义几何结构和功能,操作简单.数据结构中的一个点CGPoint代表在一个二维坐标系统.数据结构的位置和尺寸CGRect代表的一个长方形.数据结构的尺寸CGSize代表宽度和高度 ...
- 【干货】查看windows文件系统中的数据—利用簇号查看文件与恢复文件
前面我们使用这个软件发现了很多删除掉的数据,今天来看看簇.FAT文件系统中,存在一个簇的链接,我知道了簇1在哪里就可以顺藤摸瓜恢复所有的信息. 这里使用FAT 12为例子,FAT其他万变不离其宗,甚至 ...