动态性

动态语言

  • 在程序运行时,可以改变程序结构或变量类型,典型的语言:

    • Python,ruby,javascript
    • 如:
function test(){
var s = "var a=3;var b=5;alert(a+b);";
eval(s);
}

Java的动态性

  • C,C++,JAVA不是动态语言,但是JAVA有一定的动态性
  • 我们可以利用反射机制,字节码操作获得类似动态语言的特性
  • JAVA的动态性让编程的时候更加灵活

Class类

反射机制

  • 指的是可以于运行时加载,探知,使用编译期间完全未知的类
  • 程序在运行状态中,可以动态加载一个只有名称的类,对于任意一个已加载的类,都能知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性。

Class c=Class.forName("com.User");

  • "com.User"是字符串,是类的路径,可以动态的实时的加载这个类。
  • 加载完类之后,在堆内存中,就产生一个Class类型的对象,一个类只有一个Class对象,这个对象就包含了完整的类的结构信息。我们可以通过这个对象看到类的结构。这个对象像一面镜子,透过这个镜子看到类的结构。所以称之为反射、

先简单写一个com.User

public class User {
/**
*
*/
private int id;
private int age;
private String uname; public User() { } public User(int id,int age,String uname){
super();
this.id=id;
this.age=age;
this.uname=uname;
}
public String getUname() {
return uname;
} public void setUname(String uname) {
this.uname = uname;
} public int getAge() {
return age;
} public void setAge(int age) {
this.age = age;
} public int getId() {
return id;
} public void setId(int id) {
this.id = id;
}
}

获取Class对象的方式

  • 获取Class对象的三种方式
  • 1 Object ——> getClass();
  • 2 任何数据类型(包括基本数据类型int,数组等)都有一个“静态”的class属性
  • 3 通过Class类的静态方法:forName(String className)(常用)
public class Demo01 {

    public static void main(String []args){
//第一种 Object ——> getClass();
User user1 = new User();
Class clazz1=user1.getClass();
System.out.println(clazz1.hashCode()); //第二种 任何数据类型(包括基本数据类型)都有一个“静态”的class属性
Class clazz2 = User.class;
System.out.println(clazz2.hashCode()); //第三种:通过Class类的静态方法:forName(String className)(常用)
String path="com.fanshe.User";
try {
Class clazz3=Class.forName(path);
System.out.println(clazz3.hashCode());
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}

这三种方法得到的hashcode是一样的,这验证了一个类只有一个Class对象:一个工厂可以有很多辆车,但可能只有一张图纸。

反射机制的常见作用

反射的使用主要就是获取到了Class对象之后,通过调用Class对象的方法来操纵。

public class Demo02 {
public static void main(String[] args) throws NoSuchMethodException {
//第三种:通过Class类的静态方法:forName(String className)(常用)
String path="com.fanshe.User";
try {
Class clazz3=Class.forName(path);
//获得类的名字
System.out.println("\n获取类的名字: ");
System.out.println(clazz3.getName());//包名加类名
System.out.println(clazz3.getSimpleName());//类名 //获取属性信息
System.out.println("\n获取属性信息: ");
Field[] field=clazz3.getFields();
Field[] field1=clazz3.getDeclaredFields();
System.out.println(field.length+" "+field1.length);//前者只能读取public的
Field field2 = clazz3.getDeclaredField("id");
for(Field temp:field1){
System.out.println("属性: "+temp);
} //获取方法的属性
System.out.println("\n获取方法的属性: ");
Method[] methods = clazz3.getDeclaredMethods();
Method method = clazz3.getMethod("setUname", String.class);//单一方法
Method method1 = clazz3.getMethod("getUname",null);
for(Method temp:methods){
System.out.println("方法: "+temp);
} //获得构造器的信息
System.out.println("\n获得构造器信息: ");
Constructor[] constructors = clazz3.getDeclaredConstructors();
for(Constructor temp:constructors){
System.out.println("构造器: "+temp);
}
Constructor constructor = clazz3.getDeclaredConstructor(int.class,int.class,String.class);
System.out.println("有参构造器:"+clazz3);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
}
}

运行结果

获取类的名字:
com.fanshe.User
User 获取属性信息:
0 3
属性: private int com.fanshe.User.id
属性: private int com.fanshe.User.age
属性: private java.lang.String com.fanshe.User.uname 获取方法的属性:
方法: public int com.fanshe.User.getId()
方法: public java.lang.String com.fanshe.User.getUname()
方法: public void com.fanshe.User.setUname(java.lang.String)
方法: public void com.fanshe.User.setId(int)
方法: public int com.fanshe.User.getAge()
方法: public void com.fanshe.User.setAge(int) 获得构造器信息:
构造器: public com.fanshe.User()
构造器: public com.fanshe.User(int,int,java.lang.String)
有参构造器:class com.fanshe.User

通过反射API的动态操作

public class Demo03 {
public static void main(String []args){
//第三种:通过Class类的静态方法:forName(String className)(常用)
String path="com.fanshe.User";
try {
Class clazz3=Class.forName(path);
/*通过反射API调用构造方法,构造对象*/ //其实是调用了User的无参方法
User user = (User)clazz3.newInstance();
user.setUname("大王");
System.out.println(user.getUname());
//获得方法
Constructor<User> constructor = clazz3.getDeclaredConstructor(int.class,int.class,String.class);
//通过实际的参数来调用
User user1 = constructor.newInstance(1001,18,"美云");
System.out.println(user1.getUname());
/*通过反射API调用普通方法*/
//user1.setUname("小七");
User user2 =(User) clazz3.newInstance();
Method method = clazz3.getDeclaredMethod("setUname",String.class);
method.invoke(user2,"小七");
System.out.println(user2.getUname()); /*通过反射API操作属性*/
User user3 = (User)clazz3.newInstance();
Field f =clazz3.getDeclaredField("uname");
f.setAccessible(true);
f.set(user3,"小赖");
System.out.println(user3.getUname());
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
}
}

运行结果明显

大王
美云
小七
小赖

这样写有什么好处呢?可以发现setUname 是字符串,传的参数也是变量,这样的变量我们就可以从文件中读取,可以从数据库中读取,总之可以从其他地方传过来,这样就实现了动态的调用,动态创建类。

参考

[1] https://www.cnblogs.com/nullcodeworld/p/8878747.html

[2] b站:av29578196

[Java-基础]反射_Class对象_动态操作的更多相关文章

  1. Java基础-IO流对象之内存操作流(ByteArrayOutputStream与ByteArrayInputStream)

    Java基础-IO流对象之内存操作流(ByteArrayOutputStream与ByteArrayInputStream) 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.内存 ...

  2. Java基础-反射(reflect)技术详解

    Java基础-反射(reflect)技术详解 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.类加载器 1>.JVM 类加载机制  如下图所示,JVM类加载机制分为五个部分 ...

  3. 黑马程序员:Java基础总结----静态代理模式&动态代理

    黑马程序员:Java基础总结 静态代理模式&动态代理   ASP.Net+Android+IO开发 . .Net培训 .期待与您交流! 静态代理模式 public  class  Ts {   ...

  4. Java基础-IO流对象之随机访问文件(RandomAccessFile)

    Java基础-IO流对象之随机访问文件(RandomAccessFile) 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.RandomAccessFile简介 此类的实例支持对 ...

  5. Java基础-IO流对象之数据流(DataOutputStream与DataInputStream)

    Java基础-IO流对象之数据流(DataOutputStream与DataInputStream) 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.数据流特点 操作基本数据类型 ...

  6. Java基础-IO流对象之序列化(ObjectOutputStream)与反序列化(ObjectInputStream)

    Java基础-IO流对象之序列化(ObjectOutputStream)与反序列化(ObjectInputStream) 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.对象的序 ...

  7. Java基础-IO流对象之字符缓冲流(BufferedWriter与BufferedReader)

    Java基础-IO流对象之字符缓冲流(BufferedWriter与BufferedReader) 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.字符缓冲流 字符缓冲流根据流的 ...

  8. Java基础-IO流对象之字节缓冲流(BufferedOutputStream与BufferedInputStream)

    Java基础-IO流对象之字节缓冲流(BufferedOutputStream与BufferedInputStream) 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 在我们学习字 ...

  9. Java基础-IO流对象之转换流(InputStreamReader与OutoutStreamWriter)

    Java基础-IO流对象之转换流(InputStreamReader与OutoutStreamWriter) 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.转换流概述 我们之前 ...

随机推荐

  1. use matplotlib to drew a table

    $sudo apt-get install python3-matplotlib gyf@gyf-VirtualBox:~$ python3Python 3.6.9 (default, Nov  7 ...

  2. SQL注入汇总(手注,盲注,报错注入,宽字节,二次编码,http头部){10.22、23 第二十四 二十五天}

    首先什么是SQL注入: 所谓SQL注入,就是通过把SQL命令插入到Web表单提交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令. SQL注入有什么危害? 危害:数据泄露.脱库 ...

  3. UVA - 536 Tree Recovery (二叉树重建)

    题意:已知先序中序,输出后序. #pragma comment(linker, "/STACK:102400000, 102400000") #include<cstdio& ...

  4. HDU_4939 stupid tower defense 2014多校7 多变量型DP

    意思是有个塔防游戏,有三种塔,红塔在怪物经过的时候每秒会产生攻击力大小的伤害,绿塔对怪物经过以及经过之后每秒产生攻击力大小的伤害,还有种蓝塔,对怪物进行减速,即怪物从此之后经过一个单位都会减慢c秒 最 ...

  5. python --- 对于需要关联的接口处理方法

    1.unittest对于需要关联的请求,怎么处理(如购物接口,需要先登录) a)把登录请求写到测试用例类的setUP函数中,这样每次调用测试用例,都会先执行setUP函数 b)全局变量的形式声明. c ...

  6. UVA - 11806 Cheerleaders (容斥原理)

    题意:在N*M个方格中放K个点,要求第一行,第一列,最后一行,最后一列必须放,问有多少种方法. 分析: 1.集合A,B,C,D分别代表第一行,第一列,最后一行,最后一列放. 则这四行必须放=随便放C[ ...

  7. 业务全都在yun上能放心吗?

    导读 组织将其业务在云上进行“全押”,这与扑克游戏中的这个激动人心时刻有着同样的吸引力.这种举动感觉很大胆,但却向外界传达了自己的信心,表明将会果断行动赢得比赛. 大多数银行对处理零售银行业务方式需要 ...

  8. java虚拟机之JVM体系结构

    JVM体系结构: 下面重点介绍运行时数据区域模块: (1)java堆(Heap) 被所有线程共享的一块内存区域,在虚拟机启动时创建 用来存储对象实例 可以通过-Xmx和-Xms控制堆的大小 OutOf ...

  9. hadoop yarn 实战错误汇总

    1.hadoop yarn 运行wordcount时执行完成,但是返回错误 错误信息如下: // :: INFO mapreduce.Job: Job job_1441395011668_0001 f ...

  10. php base64编码图片上传七牛

    上网上找了好几个例子 都是自己写curl上传 感觉七牛这么多年了不应该sdk不提供一个方法 然后试 试 试 显示put 方式 上传上去 就是个字符串 后来换成文件上传方法 putFile 成了 不废话 ...