Java基础——反射
今天学到Java基础中的反反射。依照我学习后的个人理解呢,反射就是一套获取类、属性、方法等的工具吧。(其实,感觉学完反射后,有点像喝凉水,解渴但确实我也没体会出它有什么味道,我可能没有学到精髓吧。自己都能感觉少点什么。这是我Java基础学习的最后一个部分了,我想再复习一遍,然后再学习其他的。也想有时间看看JVM和计算机系统之类的书。总觉得自己不是科班出身,思路上有些短板。要继续努力咯。)
在学习反射之前,我先回忆了一下可变参数。
public static void main(String[] args) {
test();//调用方法1
test("JAVA");//调用方法2
test("JAVA","工程师");//调用方法3
test(new String[]{"水果","电器"});//调用方法4
} static void test(String ... array){
//直接打印:System.out.println(array);
for(String str:array){ //利用增强for遍历
System.out.println(str);
}
}
之所以回忆可变参数呢,是因为它与反射的应用有点像。如果将一个方法定义为可变参数,在调用的时候传参的限制就少了一大截。在反射当中呢,我们利用一些方法,得到类的实例对象,那么类里面的方法、属性等,就尽收眼底。在前面的学习中知道了,方法、属性等都有静态的和非静态的,私有的和非私有的之分,那么我们在调用的时候,想取哪一块,或者说只想取得哪一块,是不是也可以想个办法实现呢?这时候,反射就出现了,现今我对它的理解就只有这些了。继续努力吧。
一、反射的概念
JAVA反射机制是在运行状态中(注意不是编译的时候),对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
Java反射机制主要提供了以下功能:
-- 在运行时判断任意一个对象所属的类;
-- 在运行时构造任意一个类的对象;
-- 在运行时判断任意一个类所具有的成员变量和方法;
-- 在运行时调用任意一个对象的方法;
-- 生成动态代理。
JDK中,与反射相关的类,主要有以下几个
//java.lang包下
Class 类
Class 类的实例表示正在运行的 Java 应用程序中的类和接口。枚举是一种类,注释是一种接口。每个数组属于被映射为 Class 对象的一个类,所有具有相同元素类型和维数的数组都共享该 Class 对象。基本的 Java 类型(boolean、byte、char、short、int、long、float 和 double) 和关键字 void 也表示为 Class 对象。
关于Class类JDK里面的解释:
public final
class Class<T> implements java.io.Serializable,
java.lang.reflect.GenericDeclaration,
java.lang.reflect.Type,
java.lang.reflect.AnnotatedElement {
private static final int ANNOTATION= 0x00002000;
private static final int ENUM = 0x00004000;
private static final int SYNTHETIC = 0x00001000; private static native void registerNatives();
static {
registerNatives();
} /*
* Constructor. Only the Java Virtual Machine creates Class
* objects.
*/
private Class() {}
Class类JDK里的一些方法(个人觉得读起来很舒服,自己想记录一下)
public String toString() {
return (isInterface() ? "interface " : (isPrimitive() ? "" : "class "))
+ getName();
}//应该是三元表达式
public static Class<?> forName(String className)
throws ClassNotFoundException {
Class<?> caller = Reflection.getCallerClass();
return forName0(className, true, ClassLoader.getClassLoader(caller), caller);
}
public static Class<?> forName(String name, boolean initialize,
ClassLoader loader)
throws ClassNotFoundException
{
Class<?> caller = null;
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
// Reflective call to get caller class is only needed if a security manager
// is present. Avoid the overhead of making this call otherwise.
caller = Reflection.getCallerClass();
if (loader == null) {
ClassLoader ccl = ClassLoader.getClassLoader(caller);
if (ccl != null) {
sm.checkPermission(
SecurityConstants.GET_CLASSLOADER_PERMISSION);
}
}
}
return forName0(name, initialize, loader, caller);
}
private static native Class<?> forName0(String name, boolean initialize,
ClassLoader loader,
Class<?> caller)
throws ClassNotFoundException;
public T newInstance()
throws InstantiationException, IllegalAccessException
{
if (System.getSecurityManager() != null) {
checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), false);
} // NOTE: the following code may not be strictly correct under
// the current Java memory model. // Constructor lookup
if (cachedConstructor == null) {
if (this == Class.class) {
throw new IllegalAccessException(
"Can not call newInstance() on the Class for java.lang.Class"
);
}
try {
Class<?>[] empty = {};
final Constructor<T> c = getConstructor0(empty, Member.DECLARED);
// Disable accessibility checks on the constructor
// since we have to do the security check here anyway
// (the stack depth is wrong for the Constructor's
// security check to work)
java.security.AccessController.doPrivileged(
new java.security.PrivilegedAction<Void>() {
public Void run() {
c.setAccessible(true);
return null;
}
});
cachedConstructor = c;
} catch (NoSuchMethodException e) {
throw new InstantiationException(getName());
}
}
Constructor<T> tmpConstructor = cachedConstructor;
// Security check (same as in java.lang.reflect.Constructor)
int modifiers = tmpConstructor.getModifiers();
if (!Reflection.quickCheckMemberAccess(this, modifiers)) {
Class<?> caller = Reflection.getCallerClass();
if (newInstanceCallerCache != caller) {
Reflection.ensureMemberAccess(caller, this, null, modifiers);
newInstanceCallerCache = caller;
}
}
// Run constructor
try {
return tmpConstructor.newInstance((Object[])null);
} catch (InvocationTargetException e) {
Unsafe.getUnsafe().throwException(e.getTargetException());
// Not reached
return null;
}
}
public String getName() {
String name = this.name;
if (name == null)
this.name = name = getName0();
return name;
}
// cache the name to reduce the number of calls into the VM
private transient String name;
private native String getName0();
还有很多,暂不记录了。。。。。
//java.lang.reflect 包下
Constructor 代表构造函数
Method 代表方法
Field 代表字段
Array 与数组相关
二、Class类的说明
常用的得到Class类的方法
// Class c=new Class(); 不可以,因为它被私有化了
1) Class c=Student.class; //用类名.class 就可以得到Class类的实例
2) Student stu=new Student();
Class c=stu.getClass(); //用对象名.getClass();
3) Class c=Class.forName("com.mysql.jdbc.Driver");
//例一 通过调用无参的构造函数,创建类对象
public class Test {
public static void main(String[] args) throws InstantiationException, IllegalAccessException {
Class clazz=Dog.class;
Dog dog=(Dog)clazz.newInstance();
dog.shout();
}
} class Dog{
void shout(){
System.out.println("汪汪");
}
}
通过例一,我并没有看出来利用反射的好处,呃~~
//例二 上例的改写
Class clazz=Class.forName("com.weiboo.Dog"); //注意,必须是类的全部
Dog dog=(Dog)clazz.newInstance();
dog.shout();
//例三 (运行本类,Dog 和 Cat 类,必须有一个无参的构造函数)
public class Test {
public static void main(String[] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
Dog dog=(Dog)createObj(Dog.class);
dog.shout(); Cat cat=(Cat)createObj(Cat.class);
cat.speak();
} static Object createObj(Class clazz) throws InstantiationException, IllegalAccessException{
return clazz.newInstance(); //调用的是newInstance() 方法创建的类对象,它调用的是类中无参的构造方法
}
} class Dog{
void shout(){
System.out.println("汪汪");
}
} class Cat{
void speak(){
System.out.println("喵~~~");
}
}
三、反射中的其他的类的说明
1) Constructor
代表类中的构造函数 Class 类提供了以下四个方法
public Constructor<?>[] getConstructors() //返回类中所有的public构造器集合,默认构造器的下标为0
public Constructor<T> getConstructor(Class<?>... parameterTypes) //返回指定public构造器,参数为构造器参数类型集合
public Constructor<?>[] getDeclaredConstructors() //返回类中所有的构造器,包括私有的
public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) //返回任意指定的构造器,包括私有的
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException; //例子 得到某个类中指定的某个构造函数所对应的 Constructor对象
class Test2 {
public static void main(String[] args) throws InstantiationException,
IllegalAccessException, ClassNotFoundException,
NoSuchMethodException, SecurityException, IllegalArgumentException,
InvocationTargetException {
Class<Cat> clazz = Cat.class; Constructor<Cat> c = clazz.getConstructor(int.class, String.class);
Cat cat = (Cat) c.newInstance(20, "加飞猫");
cat.speak();
} class Cat {
private String name;
private int age; public Cat(int age, String name) {
this.age = age;
this.name = name;
} public Cat(String content) {
System.out.println("这是构造函数得到的参数" + content);
} void speak() {
System.out.println("喵~~~");
System.out.println("我的名字是" + this.name + "我的年龄是" + this.age);
}
}
}
/例子 访问类中的私有构造函数
Class clazz=Cat.class;
Constructor c=clazz.getDeclaredConstructor();
c.setAccessible(true); //让私有成员可以对外访问
Cat cat=(Cat) c.newInstance(); //对于私有的来说,能不能行?
cat.speak();
2) Method 代表类中的方法
Class 类提供了以下四个方法
public Method[] getMethods() //获取所有的共有方法的集合,包扩继承的
public Method getMethod(String name,Class<?>... parameterTypes) // 获取指定公有方法 参数1:方法名 参数2:参数类型集合
public Method[] getDeclaredMethods() //获取所有的方法(包扩私有的),除了继承来的
public Method getDeclaredMethod(String name,Class<?>... parameterTypes) //获取任意指定方法,除来了继承来的
//调用类中的私有方法
main 函数
Class clazz=Cat.class;
//调用一个不带参数的方法
Method m=clazz.getDeclaredMethod("speak");
m.setAccessible(true);
Cat c=new Cat();
m.invoke(c); //让方法执行 //调用一个带参数的方法
Method m=clazz.getDeclaredMethod("eat", int.class,String.class);
m.setAccessible(true);
Cat c=new Cat();
m.invoke(c, 20,"鱼"); class Cat{
private String name;
private int age; Cat(){
}
public Cat(int age,String name){
this.age=age;
this. name=name;
} public Cat(String content){
System.out.println("这是构造函数得到的参数"+content);
} private void speak(){
System.out.println("喵~~~");
System.out.println("我的名字是"+this.name+"我的年龄是"+this.age);
} private void eat(int time,String something){
System.out.println("我在"+time +"分钟内吃了一个"+something);
}
}
例子 查看一个类中的所有的方法名
public static void main(String[] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException {
Class clazz=Cat.class; /*Method [] methodList=clazz.getMethods() ; //查看所有的公有方法,包扩继承的
for(Method m:methodList){
System.out.println(m.getName());
}*/
Method [] methodList=clazz.getDeclaredMethods(); //查看所有的方法,包扩私有的,但不包扩继承的
for(Method m:methodList){
System.out.println(m.getName());
}
}
3) Field 代表字段
public Field getDeclaredField(String name) // 获取任意指定名字的成员
public Field[] getDeclaredFields() // 获取所有的成员变量,除了继承来的
public Field getField(String name) // 获取任意public成员变量,包含继承来的
public Field[] getFields() // 获取所有的public成员变量
//例子 访问字段
public class Test {
public static void main(String[] args) throws Exception {
Class clazz=Cat.class; /* Field field= clazz.getField("home");
Cat c=new Cat();
Object obj=field.get(c);
System.out.println(obj); // 家*/ Cat cat=new Cat();
Field [] fieldList= clazz.getDeclaredFields();
for(Field f:fieldList){ //访问所有字段
f.setAccessible(true);
System.out.println(f.get(cat));
}
}
}
class Cat{
private String name="黑猫";
private int age=2;
public String home="家";
}
四、反射的应用
用一个例子来说明一下,比较两个同类对象中的所有字段,不同的并把它输出来。
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map; public class Test {
public static void main(String[] args) throws Exception {
Student stu1 = new Student(24, "李磊", "工程大学", "女");
Student stu2 = new Student(20, "王一", "师大", "男");
Map<String, String> map = compare(stu1, stu2); for (Map.Entry<String, String> item : map.entrySet()) {
System.out.println(item.getKey() + ":" + item.getValue());
}
} static Map<String, String> compare(Student stu1, Student stu2) {
Map<String, String> resultMap = new HashMap<String, String>(); Field[] fieldLis = stu1.getClass().getDeclaredFields(); // 得到stu1所有的字段对象
try {
for (Field f : fieldLis) {
f.setAccessible(true); // 别忘了,让私有成员可以对外访问
Object v1 = f.get(stu1);
Object v2 = f.get(stu2);
if (!(v1.equals(v2))) {
resultMap.put(f.getName(), "stu1的值是" + v1 + " stu2的值是"
+ v2);
}
} } catch (Exception ex) {
ex.printStackTrace();
}
return resultMap; } } class Student {
private String name;
private String school;
private String sex; public Student(int age, String name, String school, String sex) { this.age = age;
this.name = name;
this.school = school;
this.sex = sex;
} private int age; public int getAge() {
return age;
} public void setAge(int age) {
this.age = age;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public String getSchool() {
return school;
} public void setSchool(String school) {
this.school = school;
} public String getSex() {
return sex;
} public void setSex(String sex) {
this.sex = sex;
}
}
Java基础——反射的更多相关文章
- Java基础-反射(reflect)技术详解
Java基础-反射(reflect)技术详解 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.类加载器 1>.JVM 类加载机制 如下图所示,JVM类加载机制分为五个部分 ...
- Java基础反射(二)
原文地址http://blog.csdn.net/sinat_38259539/article/details/71799078 反射是框架设计的灵魂 (使用的前提条件:必须先得到代表的字节码的Cla ...
- java基础(反射,注解,多线程,juc)
JAVA基础 java反射 class对象 三种方式获取class加载时对象 1.class.forName("全类名"):将字节码文件加载进内存,返回class对象 2.类名.c ...
- [java 基础]反射入门
原文 概况 使用java的反射,可以让我们检查(或者修改)类,接口,字段,方法的特性.当你在编译期不知道他们的名字的时候非常有用. 除此之外,可以使用反射来创建实例,调用方法或者get/set 字段值 ...
- JAVA基础-反射机制
什么是JAVA的反射机制 Java反射是Java被视为动态(或准动态)语言的一个关键性质.这个机制允许程序在运行时透过Reflection APIs取得任何一个已知名称的class的内部信息,包括其 ...
- java基础-反射(细节)
java面试题--java反射机制? Java反射机制的作用:1)在运行时判断任意一个对象所属的类.2)在运行时判断任意一个类所具有的成员变量和方法.3)在运行时任意调用一个对象的方法4)在运行时构造 ...
- Java基础—反射(转载)
转载自: JAVA反射与注解 JAVA反射 主要是指程序可以访问,检测和修改它本身状态或行为的一种能力,并能根据自身行为的状态和结果,调整或修改应用所描述行为的状态和相关的语义. 反射机制是什么 反射 ...
- java基础——反射机制
反射机制是什么 反射机制就是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称为jav ...
- Java基础—反射与代理(新手向)
第1章 反射与代理 1.1 反射定义 一般情况下,需要一个功能的前提是遇到了某个问题,这里先列举一些问题,然后再通过反射是如何解决了这些问题,来引出反射的定义. 普通开发人员工作中最常见的问题:需要生 ...
随机推荐
- 【NumberValidators】工商营业执照号码和统一社会信用代码验证
从本质上讲,工商营业执照号码和统一社会信用代码是两套完全不一样的编码规则,识别结果也仅有行政区划部分为两者共有,但因为这两种编码同时存在的原因,所以如果需要在系统中唯一标志一家企业时,还是可以通过工商 ...
- ASP.NET MVC 使用 Log4net 记录日志
Log4net 介绍 Log4net 是 Apache 下一个开放源码的项目,它是Log4j 的一个克隆版.我们可以控制日志信息的输出目的地.Log4net中定义了多种日志信息输出模式.它可以根据需要 ...
- 【BZOJ2001】 [Hnoi2010]City 城市建设
BZOJ2001 [Hnoi2010]City 城市建设 Solution 我们考虑一下这个东西怎么求解? 思考无果...... 咦? 好像可以离线cdq,每一次判断一下如果这条边如果不选就直接删除, ...
- [WC2005]双面棋盘(线段树+并查集)
线段树+并查集维护连通性. 好像 \(700ms\) 的时限把我的常数超级大的做法卡掉了, 必须要开 \(O_2\) 才行. 对于线段树的每一个结点都开左边的并查集,右边的并查集,然后合并. \(Co ...
- HDFS概要
--HDFS-- Hadoop Distributed File System HDFS一个分布式,高容错,可线性扩展的文件系统 简介: Hadoop分布式文件系统(HDFS)是一种分布式文件系统,设 ...
- flask信号使用
flask信号: 安装: flask中的信号使用的是一个第三方插件,叫做blinker.通过pip list看一下,如果没有安装,通过以下命令即可安装blinker: pip install blin ...
- FastDFS高可用集群架构配置搭建
一.基本模块及高可用架构 FastDFS 是余庆老师开发的一个开源的高性能分布式文件系统(DFS). 它的主要功能包括:文件存储,文件同步和文件访问,以及高容量和负载平衡. FastDFS 系统有 ...
- bower 和 npm 的区别
前端技术和工程实践真的是突飞猛进啊,想当年,我这个半业余前端吭哧吭哧做页面的时候,哪有这么多东西可以用啊,现在先进到我都完全看不懂了.本文主要讲一下同是包管理器的bower和npm的差别. 主要也是在 ...
- JS中this的那些事儿
this是JavaScript中最复杂的机制之一.它是一个很特别的关键字,被自动定义在所有函数的作用域中. 一.this到底指向什么? this既不指向函数自身,也不指向函数的词法作用域,具体指向什么 ...
- Supervisod的使用
原文链接:http://blog.csdn.net/xyang81/article/details/51555473 Supervisor(http://supervisord.org/)是用Pyth ...