【Java语言特性学习之二】反射
一、概念
java加载class文件分两种情况:
(1)类型是编译器已知的,这种文件的.class文件在编译的时候,编译器会把.class文件打开(不加载)检查,称为Run- Time Type Identification 运行时类型识别
(2)从其它地方获取引用,然后动态的把这个未知类型的引用的对象的.class文件加载进jvm虚拟机里,称为反射;
在运行状态中,动态获取类信息(属性、方法)及动态调用类对象方法的功能称为java的反射机制。
二、反射API
Java反射包:java.lang.reflect.*
1、获取类
首先获取类,获取到类之后,Class类提供了很多获取类属性,方法,构造方法的api
(1)obj.getClass(),这个是Object类里面的方法;
(2)User.Class属性,任何的数据类型,基本数据类型或者抽象数据类型,都可以通过这种方式获取类;
(3)Class.forName(""),Class类提供了这样一个方法,让我们通过类名来获取到对象类,使用最多;
package reflect;
import reflect.test.model.User;
public class Main {
public static void main(String[] args) throws ClassNotFoundException {
//1.通过Object类里面的方法getClass()
User u = new User();
Class c = u.getClass();
System.out.println(c);//class reflect.test.model.User
//2通过.Class属性
Class c2 = User.class;
System.out.println(c2);//class reflect.test.model.User
//3.Class.forName("全路径名")
Class c3 = Class.forName("reflect.test.model.User");
System.out.println(c3);//class reflect.test.model.User
}
}
2、获取属性和方法
package reflect.test.model;
public class User {
private String name;
private int age;
public User() {}
public User(String name,int age) {
this.name = name;
this.age = age;
}
public int a = 100;
private String str = "123456789";
public boolean dosomething(Integer a,Float b) {
System.out.println("dosomething");
return true;
}
}
package reflect; import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier; public class Main2 { public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException { /************************获取所有的属性************************/
Class<?> c = Class.forName("reflect.test.model.User");
//getDeclaredFields 获取所有的属性
Field[] fs = c.getDeclaredFields(); // 定义可变长的字符串,用来存储属性
StringBuffer sb = new StringBuffer();
// 通过追加的方法,将每个属性拼接到此字符串中
// 最外边的public定义
sb.append(Modifier.toString(c.getModifiers()) + " class " + c.getSimpleName() + "{\n");
// 里边的每一个属性
for (Field field : fs) {
sb.append("\t");// 空格
sb.append(Modifier.toString(field.getModifiers()) + " ");// 获得属性的修饰符,例如public,static等等
sb.append(field.getType().getSimpleName() + " ");// 属性的类型的名字
sb.append(field.getName() + ";\n");// 属性的名字+回车
} sb.append("}"); System.out.println(sb); /***************************获取指定属性***********************/ //获取id属性
Field idF = null;
try {
idF = c.getDeclaredField("age");
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
}
//实例化这个类赋给o
Object o = null;
try {
o = c.newInstance();
} catch (InstantiationException | IllegalAccessException e) {
e.printStackTrace();
}
//打破封装
idF.setAccessible(true); //使用反射机制可以打破封装性,导致了java对象的属性不安全。
//给o对象的id属性赋值"110"
try {
//set
idF.set(o,110);
} catch (IllegalArgumentException | IllegalAccessException e) {
e.printStackTrace();
}
//get
try {
System.out.println(idF.get(o));
} catch (IllegalArgumentException | IllegalAccessException e) {
e.printStackTrace();
} /***************************获取方法****************************/ //getDeclaredMethods() 获取所有的方法(不包含构造方法)
Method[] declaredMethods = c.getDeclaredMethods();
for (Method m:declaredMethods) {
System.out.println(m);
//getReturnType() 获得方法的放回类型
System.out.println(m.getReturnType());
//getParameterTypes() 获得方法的传入参数类型
Class<?>[] parameterTypes = m.getParameterTypes();
for(Class cc : parameterTypes) {
System.out.println(cc);
}
} //getDeclaredMethod("方法名",参数类型.class,……) 获得特定的方法
Method declaredMethod = c.getDeclaredMethod("dosomething", Integer.class,Float.class);
System.out.println(declaredMethod);
Method method = c.getMethod("dosomething", Integer.class,Float.class);
System.out.println(method);
//getDeclaredConstructors() 获取所有的构造方法
Constructor<?>[] declaredConstructors = c.getDeclaredConstructors();
for(Constructor ccc : declaredConstructors) {
System.out.println(ccc);
}
//getDeclaredConstructor(参数类型.class,……) 获取特定的构造方法
Constructor<?> declaredConstructor = c.getDeclaredConstructor(String.class,int.class);
System.out.println(declaredConstructor);
//getSuperclass() 获取某类的父类
Class<?> superclass = c.getSuperclass();
System.out.println(superclass);
//getInterfaces() 获取某类实现的接口
Class<?>[] interfaces = c.getInterfaces();
for(Class cccc: interfaces) {
System.out.println(cccc);
} } }
结果:
public class User{
private String name;
private int age;
public int a;
private String str;
}
110
public boolean reflect.test.model.User.dosomething(java.lang.Integer,java.lang.Float)
boolean
class java.lang.Integer
class java.lang.Float
public boolean reflect.test.model.User.dosomething(java.lang.Integer,java.lang.Float)
public boolean reflect.test.model.User.dosomething(java.lang.Integer,java.lang.Float)
public reflect.test.model.User()
public reflect.test.model.User(java.lang.String,int)
public reflect.test.model.User(java.lang.String,int)
class java.lang.Object
三、反射应用--动态代理
package reflect.test.intf;
public interface Interface {
public void dosomething() ;
}
package reflect.test.intf.impl;
import reflect.test.intf.Interface;
public class InterfaceImpl implements Interface {
@Override
public void dosomething() {
System.out.println("dosomething");
}
}
1、静态代理
package reflect; import reflect.test.intf.Interface;
import reflect.test.intf.impl.InterfaceImpl; /**
* 静态代理
*/
public class HandProxy implements Interface{ Interface inter = new InterfaceImpl(); @Override
public void dosomething() {
System.out.println("静态代理类");
inter.dosomething();
} }
package reflect;
public class TestHandProxy {
public static void main(String[] args) {
HandProxy p = new HandProxy();
p.dosomething();
}
}
结果:
静态代理类
dosomething
2、动态代理
package reflect; import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy; /**
* 动态代理
*/
public class AutoProxy implements InvocationHandler{
private Object target; public Object bind(Object target) {
this.target = target;
/**
* 第一个是被代理类的类构造器,
* 第二个指的是被代理类的接口,也就是Interface接口,
* 第三个是实现这个代理的类,这里就是本类。
* 这个方法执行了下面三步:
1.生成一个实现了参数interfaces里所有接口且继承了Proxy的代理类的字节码,然后用参数里的classLoader加载这个代理类。
2.使用代理类父类的构造函数 Proxy(InvocationHandler h)来创造一个代理类的实例,将我们自定义的InvocationHandler的子类传入。
3.返回这个代理类实例,因为我们构造的代理类实现了interfaces(也就是我们程序中传入的target.getClass().getInterfaces())里的所有接口,因此返回的代理类可以强转成Interface类型来调用接口中定义的方法。
*/
return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
} @Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = null;
System.out.println("动态代理");
result = method.invoke(target, args);
System.out.println("动态代理执行结束");
return result;
} }
package reflect; import reflect.test.intf.Interface;
import reflect.test.intf.impl.InterfaceImpl; public class TestAutoProxy { public static void main(String[] args) {
Interface inter = new InterfaceImpl();
AutoProxy ap = new AutoProxy();
Interface obj = (Interface)ap.bind(inter);
obj.dosomething();
} }
结果:
动态代理
dosomething
动态代理执行结束
【Java语言特性学习之二】反射的更多相关文章
- 【Java语言特性学习之一】设计模式
设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了可重用代码.让代码更容易被他人理解.保证代码可靠性. 毫无疑问,设计模式于 ...
- 【Java语言特性学习之六】扩展知识点
一.SPI机制 二.注解处理机制 三.java native关键字 https://www.cnblogs.com/KingIceMou/p/7239668.html
- 【Java语言特性学习之三】Java4种对象引用
为了更灵活的控制对象的生命周期,在JDK1.2之后,引用被划分为(引用的级别和强度由高到低)强引用.软引用.弱引用.虚引用四种类型,每种类型有不同的生命周期,它们不同的地方就在于垃圾回收器对待它们会使 ...
- 【Java语言特性学习之四】常用集合
java中常见的数据结构
- 【Java语言特性学习之五】版本差异新特性
- java之jvm学习笔记二(类装载器的体系结构)
java的class只在需要的时候才内转载入内存,并由java虚拟机的执行引擎来执行,而执行引擎从总的来说主要的执行方式分为四种, 第一种,一次性解释代码,也就是当字节码转载到内存后,每次需要都会重新 ...
- java语言特性概述
一.前言 我们都知道java是面向对象的编程,其中四个基本特性:抽象.封装.继承.多态.这四个特性,概括起来可以这么理解,抽象.封装.继承是多态的基础,多态是抽象.封装.继承的表现. 二. JAVA ...
- [原]Java修炼 之 基础篇(一)Java语言特性
学习软件开发,首先要选择的就是选择需要采用的编程语言,考虑语言本身的优缺点和实际需求,综合评价之后选择相关的语言进行系统开发.本篇博客开始就从近年来比较流行的Java开始为大家讲起. 背景 1995年 ...
- Java 语言特性
介绍以下几种语言特性: Java5的特性 1.静态引用 2.可变参数 3.自动装箱和拆箱 包装类的缓存设计 4.枚举 一.静态引用(语法糖,不推荐使用,了解一下即可) 先看看普通的引用,就是impo ...
随机推荐
- pytest框架之fixture前置和后置
一.conftest.py 定义公共的fixture,多个测试类中都可以调用 pytest提供了conftest.py文件,可以将fixture定义在此文件中 运行测试用例时,不需要去导入这个文件,会 ...
- MapReduce Shuffle 和 Spark Shuffle 原理概述
Shuffle简介 Shuffle的本意是洗牌.混洗的意思,把一组有规则的数据尽量打乱成无规则的数据.而在MapReduce中,Shuffle更像是洗牌的逆过程,指的是将map端的无规则输出按指定的规 ...
- Python爬取知乎上搞笑视频,一顿爆笑送给大家
前言 文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者:Huangwei AI 来源:Python与机器学习之路 PS:如有需 ...
- linux下 sort | uniq | wc | less 几个命令的基本用法
sort -f :忽略大小写的差异,例如 A 与 a 视为编码相同: -b :忽略最前面的空格符部分: -M :以月份的名字来排序,例如 JAN, DEC 等等的排序方法: -n :使用『纯数字』进行 ...
- hadoop mapreduce求解有序TopN
利用hadoop的map和reduce排序特性实现对数据排序取TopN条数据. 代码参考:https://github.com/asker124143222/wordcount 1.样本数据,假设是订 ...
- 一文解读PV/UV/VV/IP (转)
什么是PV? PV即Page View,网站浏览量,指页面浏览的次数,用以衡量网站用户访问的网页数量.用户每次打开一个页面便记录1次PV,多次打开同一页面则浏览量累计.一般来说,PV与来访者的数量成正 ...
- WC个人项目
一.Github项目地址: https://github.com/JakeYi/WC 二.PSP表格 PSP2.1 Personal Software Process Stages 预估耗时(分钟) ...
- 什么是测试系统工程师(TSE)?
深圳市共创力研发咨询 杨学明/文 TSE(Test System Engineer)简称测试系统工程师,作为系统工程(SE)团队的一员,很多公司目前还没有这样的角色,导致测试部分往往处理弱势,第一,不 ...
- 2.idea安装JavaCC插件.md
eclipse中插件安装JavaCC插件请参考博客:https://blog.csdn.net/qq_29232943/article/details/62439283 接下来是在idea中安 ...
- 关于ML.NET v1.0 的发布说明
今天,我们很高兴宣布发布 ML.NET 1.0.ML.NET 是一个免费的.跨平台的开源机器学习框架,旨在将机器学习(ML)的强大功能引入.NET 应用程序. ML.NET GitHub:https: ...