【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 ...
随机推荐
- swoole4创建Mysql连接池
一 .什么是mysql连接池 场景:每秒同时有1000个并发,但是这个mysql同时只能处理400个连接,mysql会宕机. 解决方案:连接池,这个连接池建立了200个和mysql的连接,这100 ...
- angularjs ng-if妙用,ng-if解决父子组件异步传值
壹 ❀ 引 angularjs开发中,组件件相互通信传值是再普遍不过的操作了,比如我在父作用域中获取了一个数据,想要传递给子组件使用,做简单的做法就是通过scope传递,比如这样: <body ...
- JeeSite | 保存信息修改记录续
遗留问题 上篇文章中遗留了一个问题,就是为了要关联类属性与注释,注释与字典的地方使用了两个map来逐个添加了相关的信息,如下所示: Map<String, String> mapField ...
- 使用ScriptX控件实现IE浏览器分页打印功能
之前讲过js调用ie浏览器自带打印的用法,今天讲使用插件的方式.浏览器自带打印不能控制页边距.页眉页脚等选项,尤其是如果分页打印的话,无法自动将前一页标题带到本页,所以不适用多页打印的功能.使用Scr ...
- Python爬取6271家死亡公司数据,看十年创业公司消亡史
前言 文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者: 朱小五 凹凸玩数据 PS:如有需要Python学习资料的小伙伴可以加 ...
- Linux(ubuntu) 三行代码搞定安装谷歌浏览器
wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb 然后再输入: sudo dpkg -i g ...
- [20190524]浅谈模糊查询.txt
[20190524]浅谈模糊查询.txt --//一台生产系统遇到监听进程莫名down的情况,3月份曾经遇到的情况,链接:http://blog.itpub.net/267265/viewspace- ...
- SRDC - ORA-30036: Checklist of Evidence to Supply (Doc ID 1682700.1)
SRDC - ORA-30036: Checklist of Evidence to Supply (Doc ID 1682700.1) Action Plan 1. Execute srdc_db_ ...
- MIPI CSI2学习(一):说一说MIPI CSI2
1. MIPI CSI2简介 MIPI联盟是一个开放的会员制组织.2003年7月,由美国德州仪器(TI).意法半导体(ST).英国ARM和芬兰诺基亚(Nokia)4家公司共同成立.MIPI联盟旨在推进 ...
- [PHP] 配置vscode的语法检测消除提示Cannot validate since no PHP executable is set
默认下载完vscode什么都不做,会提示一下信息Cannot validate since no PHP executable is set. Use the setting 'php.validat ...