一:介绍

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 的反射机制的更多相关文章

  1. Java 类反射机制分析

    Java 类反射机制分析 一.反射的概念及在Java中的类反射 反射主要是指程序可以访问.检测和修改它本身状态或行为的一种能力.在计算机科学领域,反射是一类应用,它们能够自描述和自控制.这类应用通过某 ...

  2. java的反射机制

    一.java的反射机制浅谈 最近研究java研究得很给力,主要以看博文为学习方式.以下是我对java的反射机制所产生的一些感悟,希望各位童鞋看到失误之处不吝指出.受到各位指教之处,如若让小生好好感动, ...

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

    一.Java的反射机制   每个Java程序执行前都必须经过编译.加载.连接.和初始化这几个阶段,后三个阶段如下图:   其中

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

    一.反射之实例化Class类的5种方式: java的数据类型可以分为两类,即引用类型和原始类型(即基本数据类型). 对于每种类型的对象,java虚拟机会实例化不可变的java.lang.Class对象 ...

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

    上次写JAVA的反射机制学习笔记(一)的时候,还是7月22号,这些天就瞎忙活了.自己的步伐全然被打乱了~不能继续被动下去.得又一次找到自己的节奏. 4.获取类的Constructor 通过反射机制得到 ...

  6. java笔录---反射机制(1)

    引言   为了方便记忆java的反射机制,在这里仔细的总结了一下.主要是怕以后忘记了,这样也方便回忆.因为最近利用空余时间深入的了解spring和Mybatis框架,   像spring中核心模块IO ...

  7. Java高新技术 反射机制

     Java高新技术 反射机制 知识概要:                   (1)反射的基石 (2)反射 (3)Constructor类 (4)Field类 (5)Method类 (6)用反射方 ...

  8. java的反射机制浅谈(转)

    原文链接:java的反射机制浅谈 一.java的反射机制浅谈 1.何谓反射机制 根据网文,java中的反射机制可以如此定义: JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性 ...

  9. 【转】Java利用反射机制访问私有化构造器

    Java利用反射机制访问私有化构造器 博客分类: java   我们都知道,当一个类的构造方法被设为私有的时候(private),在其他类中是无法用new来实例化一个对象的. 但是有一种方法可以把带有 ...

  10. 【转】java原理—反射机制

    一.什么是反射:反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问.检测和修改它本身状态或行为的一种能力.这一概念的提出很快引发了计算机科学领域关于应用反射性的研究.它首先被程序语言 ...

随机推荐

  1. 动态dp 板子

    动态dp 瞎扯两句吧 先从序列上理解,维护链的最大独立集. 考虑是从左边转移的,那么矩阵的转移唯一,直接放在线段树上就可以了. 放在树上的话,儿子都可以转移,把轻儿子的转移放在子链链头更新,然后每条链 ...

  2. python Popen卡死问题

    程序经常卡死,定位了半天才定位到原因,原来是Popen导致的卡死: 程序如下: s = subprocess.Popen([*,*,*], stdout=subprocess.PIPE) ret = ...

  3. Solr记录-solr内核与索引

    Solr核心(内核) Solr核心(Core)是Lucene索引的运行实例,包含使用它所需的所有Solr配置文件.我们需要创建一个Solr Core来执行索引和分析等操作. Solr应用程序可以包含一 ...

  4. 【官方文档】Nginx模块Nginx-Rtmp-Module学习笔记(一) RTMP 命令详解

    源码地址:https://github.com/Tinywan/PHP_Experience 说明: rtmp的延迟主要取决于播放器设置,但流式传输软件,流的比特率和网络速度(以及响应时间“ping” ...

  5. 转自知乎大神----JS 闭包是什么

    大名鼎鼎的闭包!这一题终于来了,面试必问. 请用自己的话简述 什么是「闭包」. 「闭包」的作用是什么. --------------------------------------- 首先来简述什么是 ...

  6. 第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 ...

  7. Anaconda+django写出第一个web app(六)

    今天学习如何写一个注册用户的界面. 上一节的导航栏中我们修改了导航栏右侧的文字为register并将路径设置为/register,内容如下: <li><a href="/r ...

  8. 洛谷 P4910 帕秋莉的手环 矩阵乘法+快速幂详解

    矩阵快速幂解法: 这是一个类似斐波那契数列的矩乘快速幂,所以推荐大家先做一下下列题目:(会了,差不多就是多倍经验题了) 注:如果你不会矩阵乘法,可以了解一下P3390的题解 P1939 [模板]矩阵加 ...

  9. objective-c 几何类常用方法整理

    CGGeometry参考定义几何结构和功能,操作简单.数据结构中的一个点CGPoint代表在一个二维坐标系统.数据结构的位置和尺寸CGRect代表的一个长方形.数据结构的尺寸CGSize代表宽度和高度 ...

  10. 【干货】查看windows文件系统中的数据—利用簇号查看文件与恢复文件

    前面我们使用这个软件发现了很多删除掉的数据,今天来看看簇.FAT文件系统中,存在一个簇的链接,我知道了簇1在哪里就可以顺藤摸瓜恢复所有的信息. 这里使用FAT 12为例子,FAT其他万变不离其宗,甚至 ...