反射(reflection),通过反射创建对象
简单尝试:
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; public class animal {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
Class name = Class.forName("com.zjl.test.reflection.cat");
Object o = name.newInstance();
Method who = name.getMethod("who");
who.invoke(o);
}
}
一、反射机制:
1.反射机制允许程序在执行期借助于Reflection
API取得任何类的内部信息(比如成员变量,构造器,成员方法等等),并能操作对象的属性及方法。反射在设计模式和框架底层都会用到
2.加载完类之后,在堆中就产生了一个Class类型
的对象(一个类只有一个Class对象),这个对象包含了类的完整结构信息。通过这个对象得到类的结构。这个对象就像一面镜子,透过这个镜子看到类的结构,所以,形象的称之为:反射
应用实例:
获取class类的四种方法:
public class GetClass_ {
public static void main(String[] args) throws ClassNotFoundException { //1. Class.forName
String classAllPath = "com.hspedu.Car"; //通过读取配置文件获取
Class<?> cls1 = Class.forName(classAllPath);
System.out.println(cls1); //2. 类名.class , 应用场景: 用于参数传递
Class cls2 = Car.class;
System.out.println(cls2); //3. 对象.getClass(), 应用场景,有对象实例
Car car = new Car();
Class cls3 = car.getClass();
System.out.println(cls3); //4. 通过类加载器【4种】来获取到类的Class对象
//(1)先得到类加载器 car
ClassLoader classLoader = car.getClass().getClassLoader();
//(2)通过类加载器得到Class对象
Class cls4 = classLoader.loadClass(classAllPath);
System.out.println(cls4); //cls1 , cls2 , cls3 , cls4 其实是同一个对象
System.out.println(cls1.hashCode());
System.out.println(cls2.hashCode());
System.out.println(cls3.hashCode());
System.out.println(cls4.hashCode()); //5. 基本数据(int, char,boolean,float,double,byte,long,short) 按如下方式得到Class类对象
Class<Integer> integerClass = int.class;
Class<Character> characterClass = char.class;
Class<Boolean> booleanClass = boolean.class;
System.out.println(integerClass);//int //6. 基本数据类型对应的包装类,可以通过 .TYPE 得到Class类对象
Class<Integer> type1 = Integer.TYPE;
Class<Character> type2 = Character.TYPE; //其它包装类BOOLEAN, DOUBLE, LONG,BYTE等待
System.out.println(type1); //两个类型是相同的:
System.out.println(integerClass.hashCode());//?
System.out.println(type1.hashCode());//? }
}
二、类加载
基本说明:
反射机制是java实现动态语言的关键,也就是通过反射实现类动态加载。
1.静态加载:编译时加载相关的类,如果没有则报错,依赖性太强
2动态加载:运行时加载需要的类,如果运行时不用该类,则不报错,降低了依赖性
3.举例说明
类加载时机:
1.当创建对象时(new) //静态加载
2.当子类被加载时,父类也加载 //静态加载
3.调用类中的静态成员时 //静态加载
4.通过反射 //动态加载
类加载:
类加载各阶段完成任务:
加载阶段:
JVM在该阶段的主要目的是将字节码从不同的数据源(可能是 class 文件、也可能是jar包,甚至网络)转化为二进制字节流加载到内存中,并生成一个代表该类的
java.lang.Class对象
连接阶段-验证:
连接阶段-准备:
变量的准备简介:
连接阶段-解析:
1.虚拟机将常量池内的符号引用替换为直接引用的过程。
初始化(Initiaalization):
1.到初始化阶段,才真正开始执行类中定义的Java程序代码,此阶段是执行
<clinit>0方法的过程。
2.<clinit>()方法是由编译器按语句在源文件中出现的顺序,依次自动收集类中的所有
静态变量的赋值动作和静态代码块中的语句,并进行合并。
3.虚拟机会保证一个类的<clinit>()方法在多线程环境中被正确地加锁、同步,如果
多个线程同时去初始化一个类,那么只会有一个线程去执行这个类的<clinit>()方法,其他线程都需要阻塞等待,直到活动线程执行<clinit>()方法完毕[debug源码]
通过反射获取类的结构信息:
java.lang.class类:
1. getName:获取全类名
2. getSimpleName:获取简单类名
3. getFields:获取所有public修饰的属性,包含本类以及父类的
4. getDeclaredFields:获取本类中所有属性
5. getMethods:获取所有public修饰的方法,包含本类以及父类的
6. getDeclaredMethods:获取本类中所有方法
7. getConstructors: 获取所有public修饰的构造器,本类
8. getDeclaredConstructors:获取本类中所有构造器
9. getPackage:以Package形式返回包信息
10.getSuperClass:以Class形式返回父类信息
11.getlnterfaces:以Class[形式返回接口信息
12.getAnnotations:以Annotation[]形式返回注解信息
java.lang.reflect.Field类:
1. getModifiers:以int形式返回修饰符
[说明:默认修饰符是0,public是1,private是2,protected是4,static是8,final是16], public(1) + static (8) = 9
2.getType:以Class形式返回类型
3.getName:返回属性名
java.lang.reflect.Method类:
1.getModifiers:以int形式返回修饰符
[说明:默认修饰符是0,public 是1,private是2,protected是4,static是8,final是16]
2.getReturnType:以Class形式获取返回类型
3.getName:返回方法名
4. getParameterTypes:以Class[返回参数类型数组
java.lang.reflect.Constructor类:
1.getModifiers: 以int形式返回修饰符
2.getName:返回构造器名(全类名)
3.getParameterTypes:以Class[]返回参数类型数组
三、通过反射实现类加载:
访问构造器:
1、方法一:调用类中的public修饰的无参构造器
2、方式二:调用类中指定构造器
3. Class类相关方法
newlnstance:调用类中的无参构造器,获取对应类的对象
getConstructor(Class...clazz):根据参数列表,获取对应的public构造器对象getDecalaredConstructor(Class...clazz):根据参数列表,获取对应的所有构造器对象
4. Constructor类相关方法
setAccessible:暴破
newlnstance(Object...obj):调用构造器
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException; public class ReflectCreateInstance {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
//1、获取User的class对象
Class<?> aClass = Class.forName("com.zjl.test.reflection.User");
//2、通过public的无参构造器创建实例
Object o = aClass.newInstance();
System.out.println(o);
//3、通过public的有参构造器创建实例
//得到构造器对象
Constructor<?> constructor = aClass.getConstructor(String.class);
//创建实例,并传入参数
Object who = constructor.newInstance("who");
System.out.println(who);
//4.通过非public的有参构造器创建实例
//得到一个private的构造器对象
Constructor<?> declaredConstructor = aClass.getDeclaredConstructor(int.class, String.class);
//对该构造器进行暴破,使得可以通过反射语句访问private的构造器,方法,属性
declaredConstructor.setAccessible(true);
//创建一个private对象的实例并赋值
Object o1 = declaredConstructor.newInstance(20, "Where");
System.out.println(o1);
}
}
class User{
private int age = 10;
private String name = "hello"; public User(){ } public User(String name) {
this.name = name;
} private User(int age, String name) {
this.age = age;
this.name = name;
} @Override
public String toString() {
return "User{" +
"age=" + age +
", name='" + name + '\'' +
'}';
}
}
访问类中的属性成员:
1.根据属性名获取Field对象
Field f =clazz对象.getDeclaredField(属性名);
2.暴破:f.setAccessible(true);1/f 是Field
3.访问
f.set(o,值);1/ o表示对象
syso(f.get(o))://o表示对象
4.注意:如果是静态属性,则set和get中的参数o,可以写成null
通过反射访问类中的方法成员:
1.根据方法名和参数列表获取Method方法对象:Method m =
clazz.getDeclaredMethod(方法名,XX.class);
2.获取对象:Object o=clazz.newlnstance);
3.暴破:m.setAccessible(true);
4.访问:Object returnValue = m.invoke(o,实参列表);
5.注意:如果是静态方法,则invoke的参数o,可以写成null!
反射(reflection),通过反射创建对象的更多相关文章
- .NET 反射(Reflection)
这节讲一下.NET 中的一个技术:反射(Reflection). 反射是一种很重要的技术,它可以在程序运行时,动态的获取类的实例,并调用实例中的任何方法.它就像一面镜子,映射出一个类的所有细节. ...
- [.net 面向对象程序设计进阶] (21) 反射(Reflection)(下)设计模式中利用反射解耦
[.net 面向对象程序设计进阶] (21) 反射(Reflection)(下)设计模式中利用反射解耦 本节导读:上篇文章简单介绍了.NET面向对象中一个重要的技术反射的基本应用,它可以让我们动态的调 ...
- [整理]C#反射(Reflection)详解
本人理解: 装配件:Assembly(程序集) 晚绑定:后期绑定 MSDN:反射(C# 编程指南) -----------------原文如下-------- 1. 什么是反射2. 命名空间与装配件的 ...
- c#之反射(Reflection)
一.反射是什么 反射就是.Net FrameWork框架为我们提供的一个帮助类库,它可以读取我们通过编译后生成的dll和exe文件里面metadate的信息. 反射可以动态的加载dll和exe文件,动 ...
- C#反射(Reflection)详解
1. 什么是反射2. 命名空间与装配件的关系3. 运行期得到类型信息有什么用4. 如何使用反射获取类型5. 如何根据类型来动态创建对象6. 如何获取方法以及动态调用方法7. 动态创建委托 1.什么是反 ...
- C# 反射Reflection——反射反射程序员的快乐
一.什么是反射 反射Reflection:System.Reflection,是.Net Framework提供的一个帮助类库,可以读取并使用metadata. 反射是无处不在的,MVC-Asp.Ne ...
- [.net 面向对象程序设计进阶] (20) 反射(Reflection)(上)利用反射技术实现动态编程
[.net 面向对象程序设计进阶] (20) 反射(Reflection)(上)利用反射技术实现动态编程 本节导读:本节主要介绍什么是.NET反射特性,.NET反射能为我们做些什么,最后介绍几种常用的 ...
- CSharpGL(43)环境映射(Environment Mapping)-天空盒(Skybox)反射(Reflection)和折射(Refraction)
CSharpGL(43)环境映射(Environment Mapping)-天空盒(Skybox)反射(Reflection)和折射(Refraction) 开始 如图所示,本文围绕GLSL里的sam ...
- 代理(Proxy)和反射(Reflection)
前面的话 ES5和ES6致力于为开发者提供JS已有却不可调用的功能.例如在ES5出现以前,JS环境中的对象包含许多不可枚举和不可写的属性,但开发者不能定义自己的不可枚举或不可写属性,于是ES5引入了O ...
- C#-反射reflection
目录 简介 引入 1.新建类库 2. 类库的使用 3.反射 反射实例1 反射实例2 反射实例3 C# shanzm 简介 反射(reflection)是什么? 在<精通C#>中是这么说的& ...
随机推荐
- Hadoop Jobhistory配置启用
Hadoop Jobhistory记录下已运行完的MapReduce作业信息并存放在指定的HDFS目录下, 默认情况下是没有启动的,需要配置完后手工启动服务. 1.修改hadoop的配置文件mapre ...
- MongoDB高级应用之高可用方案实战(4)
1.MongDB启动与关闭 1.1.命令行启动 ./mongod --fork --dbpath=/opt/mongodb/data ----logpath=/opt/mongodb/log/mong ...
- nginx高并发配置详解
https://www.cnblogs.com/liqiu/p/3152206.html 1. worker_processes 8; nginx 进程数,建议按照cpu 数目来指定,一般为它的倍数 ...
- dnspython模块报错 AttributeError: 'CNAME' object has no attribute 'address'
有时候用到这个模块的时候会报错 AttributeError: 'CNAME' object has no attribute 'address' 如下所示 [root@ansible ch01]# ...
- SYCOJ2205超级百钱百鸡
题目-超级百钱百鸡 (shiyancang.cn) 百钱百鸡的加强版 百钱百鸡的话,因为是有范围,所以挨个挨个尝试即可,确定两个,即可确定第三个. 超级百钱百鸡,通过题目的描述,最后可以得到一个二元的 ...
- 还在用visio?这款画图工具才是真的绝!
最近有读者私信我,问我推文的配图是用什么工具画的,很好看,也想学习一下.今天就给大家介绍一下这款画图工具--Draw.io 概述 draw.io是一款免费的网页版画图工具(也有桌面版),支持流程图.U ...
- Android官方文档翻译 十八 4.2Pausing and Resuming an Activity
Pausing and Resuming an Activity 暂停和恢复一个activity This lesson teaches you to 这节课教给你 Pause Your Activi ...
- Tomcat-如何创建动态的web工程及目录介绍
1,IDEA中如何创建动态web工程 (1)创建一个新模块 (2)选择你要创建什么类型的模块 (3)输入模块名,finish完成创建 创建成功如下图: 一般在WEB-INF下建一个lib目录 存放ja ...
- linux下查看开放的端口
Nmap是一款针对大型网络的端口扫描工具,它也适用于单机扫描,它支持很多扫描,也同时支持性能和可靠性统计. [root@localhost ~]# yum install namp [root@loc ...
- windows系统配置Nginx使用SSL证书实现Https反向代理
Nginx反向代理服务,可以代理接收请求,并把请求转发到设置好的其他服务器上. 例如,Nginx服务器为 100.101.102.103,A服务为 100.101.102.104 ,通过Nginx配置 ...