一,获取私有的属性,方法,构造器(俗名:暴力反射)

现有一个类,属性,方法,构造器均为私有的,如何创建实例对象,更该属性值,调用方法?

public class Student {
private String name;
private int age;
private Student() {
System.out.println("调用了Student()无参私有构造器");
}
private String info() {
System.out.println("调用了info()无参私有方法");
return "Student [name=" + name + ", age=" + age + "]";
}
private void look(String str) {
System.out.println("调用了look(String str)参数为String类型的私有方法,参数为:"+str);
}
}

main方法:

首先要创建Student类的实例对象,即调用该类私有的构造方法

public static void main(String[] args) {
try {
//1.首先要创建Student类的实例对象
//1.1创建Student类的反射对象
Class<Student> clazz = Student.class;
//1.2获取私有构造器
Constructor<Student> c0 = clazz.getDeclaredConstructor();
//1.3设置访问权限
c0.setAccessible(true);
//1.4创建实例对象
Student student = c0.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
}

运行,控制台输出结果:

调用了Student()无参私有构造器

证明调用了Student类的构造器,并创建了该类的一个实例对象

更改,获取该类的私有属性

public static void main(String[] args) {
try {
//1.首先要创建Student类的实例对象
//1.1创建Student类的反射对象
Class<Student> clazz = Student.class;
//1.2获取私有构造器
Constructor<Student> c0 = clazz.getDeclaredConstructor();
//1.3设置访问权限
c0.setAccessible(true);
//1.4创建实例对象
Student student = c0.newInstance(); //获取私有属性 name
Field name = clazz.getDeclaredField("name");
//设置访问权限
name.setAccessible(true);
//为该对象的该属性赋值
name.set(student, "张三"); Field age = clazz.getDeclaredField("age");
age.setAccessible(true);
age.set(student, 18);
//获取该属性的值:get(实例对象)
Object nameVal = name.get(student);
System.out.println("name:"+nameVal);
Object ageVal = age.get(student);
System.out.println("age:"+ageVal); } catch (Exception e) {
e.printStackTrace();
}
}

运行结果:

调用了Student()无参私有构造器
name:张三
age:18

调用私有方法

public static void main(String[] args) {
try {
//1.首先要创建Student类的实例对象
//1.1创建Student类的反射对象
Class<Student> clazz = Student.class;
//1.2获取私有构造器
Constructor<Student> c0 = clazz.getDeclaredConstructor();
//1.3设置访问权限
c0.setAccessible(true);
//1.4创建实例对象
Student student = c0.newInstance(); //获取私有属性 name
Field name = clazz.getDeclaredField("name");
//设置访问权限
name.setAccessible(true);
//为该对象的该属性赋值
name.set(student, "张三"); Field age = clazz.getDeclaredField("age");
age.setAccessible(true);
age.set(student, 18);
//获取该属性的值:get(实例对象)
Object nameVal = name.get(student);
System.out.println("name:"+nameVal);
Object ageVal = age.get(student);
System.out.println("age:"+ageVal); //获取info方法
Method infoMethod = clazz.getDeclaredMethod("info");
//设置访问权限
infoMethod.setAccessible(true);
//执行该方法,获取返回值
Object infoRet = infoMethod.invoke(student);
//打印返回值
System.out.println(infoRet); //获取look方法
Method lookMethod = clazz.getDeclaredMethod("look", String.class);
//设置访问权限
lookMethod.setAccessible(true);
//执行该方法,传参
lookMethod.invoke(student, "Hello World"); } catch (Exception e) {
e.printStackTrace();
}
}

运行结果:

调用了Student()无参私有构造器
name:张三
age:18
调用了info()无参私有方法
Student [name=张三, age=18]
调用了look(String str)参数为String类型的私有方法,参数为:Hello World

小结:通过java反射机制,可以调用任意类中的任意修饰符的属性,方法,构造器

java的反射机制跟封装冲突吗?

一个房子,没有门,没有窗户,但我为了进去,只能穿墙了...

二,通过反射机制灵活调用(多态)

先上一组简单代码

public interface Father {
void look();
String see(String str);
}
public class AAA implements Father{
@Override
public void look() {
System.out.println("this is AAA look()");
}
@Override
public String see(String str) {
System.out.println("this is AAA see()");
System.out.println("str is " + str);
return str;
}
}
public class BBB implements Father{
@Override
public void look() {
System.out.println("this is BBB look()");
}
@Override
public String see(String str) {
System.out.println("this is BBB see()");
System.out.println("str is " + str);
return str;
}
}
public class Test01 {
public static void main(String[] args) {
Father a = new AAA();
a.look();
String seeA = a.see("Hello");
System.out.println(seeA);
System.out.println("==================");
Father b = new BBB();
b.look();
String seeB = b.see("Hello");
System.out.println(seeB);
}
}

打印结果:

this is AAA look()
this is AAA see()
str is Hello
Hello
==================
this is BBB look()
this is BBB see()
str is Hello

当我们需要在程序运行时,有选择性的调用AAA类或BBB类

即:运行时编译,我们增加一个工厂类

public class Factory {
public static Father getInstance(String className) {
if("AAA".equals(className)) {
return new AAA();
}else if("BBB".equals(className)) {
return new BBB();
}else {
return null;
}
}
}

在main方法中调用:

public static void main(String[] args) {
//可从外部获取(properties文件,数据库,或其他方法返回值)
String className = "BBB"; Father a = Factory.getInstance(className);
a.look();
String seeA = a.see("Hello");
System.out.println(seeA);
}

这样,我们就可以在运行时选择性的创建对象了

这和反射有什么关系呢?

假设,需求变更,要增加一个CCC类,同样实现了Father接口,并也动态调用

需要修改的代码:

//增加一个CCC类,实现Father接口
public class CCC implements Father{
@Override
public void look() {
System.out.println("this is CCC look()");
}
@Override
public String see(String str) {
System.out.println("this is CCC see()");
System.out.println("str is " + str);
return str;
}
}
//修改Factory工厂类,增加CCC类的创建方法
public class Factory {
public static Father getInstance(String className) {
if("AAA".equals(className)) {
return new AAA();
}else if("BBB".equals(className)) {
return new BBB();
}else if("CCC".equals(className)){
return new CCC();
}else {
return null;
}
}
}

注意:在实际项目中,修改一个已经运行成功没问题的方法,是存在风险的,改完万一出错了呢...(程序员都懂...)

所以,在这里如果使用反射机制,就更加灵活,以下代码举例说明

public class Factory {
public static Father getInstance(String className) {
Father f = null; // if("AAA".equals(className)) {
// return new AAA();
// }else if("BBB".equals(className)) {
// return new BBB();
// }else if("CCC".equals(className)){
// return new CCC();
// }else {
// return null;
// } try {
f = (Father)Class.forName(className).newInstance();
} catch (Exception e) {
e.printStackTrace();
} return f;
}
}
public class Test01 {
public static void main(String[] args) {
//可从外部获取(properties文件,数据库,或其他方法返回值)
String className = "com.dream.springboot.test.clazzTest.BBB"; Father f = Factory.getInstance(className);
f.look();
String see = f.see("Hello");
System.out.println(see);
}
}

在Factory工厂类中,使用全类名获取实例,这样避免了增加类时就修改Factory类中的方法,可减少错误,也减少工作量

总结:反射就是当詹姆斯·高斯林给你关了一扇门,又给你打开的一扇窗

代码上传地址:https://download.csdn.net/download/lijian0420/10803158

java 反射运用的更多相关文章

  1. 第28章 java反射机制

    java反射机制 1.类加载机制 1.1.jvm和类 运行Java程序:java 带有main方法的类名 之后java会启动jvm,并加载字节码(字节码就是一个类在内存空间的状态) 当调用java命令 ...

  2. Java反射机制

    Java反射机制 一:什么事反射机制 简单地说,就是程序运行时能够通过反射的到类的所有信息,只需要获得类名,方法名,属性名. 二:为什么要用反射:     静态编译:在编译时确定类型,绑定对象,即通过 ...

  3. java反射(基础了解)

    package cn.itcast_01; /** *Person类 */ public class Person {    /** 姓名 */    private String name;     ...

  4. java基础知识(十一)java反射机制(上)

    java.lang.Class类详解 java Class类详解 一.class类 Class类是java语言定义的特定类的实现,在java中每个类都有一个相应的Class对象,以便java程序运行时 ...

  5. java基础知识(十一)java反射机制(下)

    1.什么是反射机制? java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法,对于任意一个对象都能够调用他的属性和方法,这种动态获取属性和方法的功能称为java的反射机制. ...

  6. java反射学习之二万能EXCEL导出

    一.EXCEL导出的实现过程 假设有一个对象的集合,现在需要将此集合内的所有对象导出到EXCEL中,对象有N个属性:那么我们实现的方式是这样的: 循环这个集合,在循环集合中某个对象的所有属性,将这个对 ...

  7. java反射学习之一反射机制概述

    一.反射机制背景概述 1.反射(reflection)是java被视为动态语言的一个关键性质 2.反射机制指的是程序在运行时能获取任何类的内部所有信息 二.反射机制实现功能概述 1.只要给定类的全名, ...

  8. java反射 之 反射基础

    一.反射 反射:JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称为 ...

  9. java反射 cglib asm相关资料

    有篇文章对java反射的调用的效率做了测试,写的比较好.猛击下面地址 http://www.blogjava.net/stone2083/archive/2010/09/15/332065.html ...

  10. 超详细的java反射教程

    看技术博客时,看到关于java反射的博文,写的非常好.猛击下面的地址,开始java反射之旅 中文翻译地址:http://ifeve.com/java-reflection/ 英文原版地址:http:/ ...

随机推荐

  1. ci完整集成

    http://www.cnblogs.com/zhanchenjin/p/5032218.html http://blog.csdn.net/williamwanglei/article/detail ...

  2. IFRAME动态加载触发onload事件(转)

    原文地址:http://blog.ops.cc/webtech/javascript/f5nhm.html <body> <script>var iframe = docume ...

  3. ubuntu中 python升级 (转载)

    转自:http://blog.csdn.net/menglin8908/article/details/16822171 在ubuntu12.04中内置的python版本为2.7.3,最近想把pyth ...

  4. Android 在eclipse中没有出现AVD的解决方法(转载)

    转自:http://frabbit2013.blog.51cto.com/1067958/1243549 本文主要介绍在系统中成功配置好Android开发环境(即SDK is ok and ADT o ...

  5. bzoj 1652: [Usaco2006 Feb]Treats for the Cows【区间dp】

    裸的区间dp,设f[i][j]为区间(i,j)的答案,转移是f[i][j]=max(f[i+1][j]+a[i](n-j+i),f[i][j-1]+a[j]*(n-j+i)); #include< ...

  6. bzoj 1827: [Usaco2010 Mar]gather 奶牛大集会【树形dp】

    不能用read会TLE!!不能用read会TLE!!不能用read会TLE!! 一开始以为要维护每个点,线段树写了好长(还T了-- 首先dfs一遍,求出点1为集会地点的答案,处理处val[u]为以1为 ...

  7. GG_DataAccess 数据库访问层使用dapper操作

    3.5.GG_DataAccess 数据库访问层使用dapper操作 和Model实体类同理,tt模板已写好,需要的可加qq群:547765059  自己下载.

  8. linux vi 块操作、多窗口

    vim 块选择v:字符选择或者行选择[ctrl]+v: 块选择y:将反白的地方复制d:将反白的地方删除 多窗口:sp {filename} 打开一个新的窗口[ctrl]+w+j或者[ctrl]+w+向 ...

  9. WMI 技术

    什么是WMI? Windows Management Instrumentation (WMI)是可伸缩的系统管理结构,该规范采用一个统一.基于标准且可扩展的面向对象接口.它提供与系统管理员信息和基础 ...

  10. STL之set和multiset

    set是与集合相关的容器,STL为我们提供了set的实现,在编程题中遇见集合问题直接调用是十分方便 SET set模版类的定义在头文件<set>中. 定义set对象的示例代码如下: set ...