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.运行结果

  java 的反射机制

-----------------------------------------------------------------------------------------------#反射重点#---------------------------------------------------------------------------------------------------

三:实现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类。

  java 的反射机制

四:类的加载器(解释一下上面方式四中类的加载器,次要内容)

1.介绍

  java 的反射机制

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.运行结果

  java 的反射机制

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.运行结果

  java 的反射机制

五:创建运行时类对象(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.运行结果

  java 的反射机制

六:重新构建复杂的即将被反射的类

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.运行结果

  使用###进行将两种方式进行隔离。

  java 的反射机制

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.运行结果

  java 的反射机制

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.运行结果

  java 的反射机制

八:获取与调用对应类运行时的方法

  包括两种:

    *获取所有方法

    *调用指定方法

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.运行结果

  java 的反射机制

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.运行结果

  java 的反射机制

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.运行结果

  java 的反射机制

九:获取构造器

  包括:

    *所有的构造器

    *调用指定的构造器

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.运行结果

  java 的反射机制

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.运行结果

  java 的反射机制

十:获取其他的内容(父类,接口,注解,包,)

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.运行结果

  java 的反射机制

十一:动态代理

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.运行结果

  java 的反射机制

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.运行结果

  java 的反射机制

十二:动态代理与静态代理的区别

  2017.12.21,今天查看了一下他们之间的区别,在这篇文章中解释的挺好的,就没有重新整理,直接粘贴一下链接。

  http://blog.csdn.net/hejingyuan6/article/details/36203505。

  在这篇文章中,这一段比我上面的程序写的更好理解:

  java 的反射机制

  

上一篇:SQL Server-索引故事的遥远由来,原来是这样的?(二十八)


下一篇:Yellow