java动态性_Java动态性之反射机制(reflection)

说到反射机制,第一次接触的人可能会比较懵,反射?什么反射?怎么反射?反射是干嘛的?下面我将在这篇文章中讲讲Java的反射机制

不过在这之前,还有一个问题需要解决,标题名中的动态性,说起动态性,我先介绍介绍动态语言和静态语言

静态语言

静态语言是在编译时变量的数据类型即可确定的语言,多数静态类型语言要求在使用变量之前必须声明数据类型。 例如:C++、Java、Delphi、C#等。

动态语言

动态语言是在运行时确定数据类型的语言。变量使用之前不需要类型声明,通常变量的类型是被赋值的那个值的类型。 例如PHP/ASP/Ruby/Python/Perl/ABAP/SQL/JavaScript/Unix Shell等等。并且动态语言,是指程序在运行时可以改变其结构:新的函数可以引进,已有的函数可以被删除等结构上的变化。

这时可能你就会有疑问了,既然Java属于静态语言,又怎么会有动态性?其一就是Java存在与动态性相关的机制:反射机制。Java通过反射机制,可以在程序运行时加载,探知和使用编译期间完全未知的类,并且可以生成相关类对象实例,从而可以调用其方法或则改变某个属性值。所以JAVA也可以算得上是一个半动态的语言。

下面来讲讲反射机制

反射机制概念

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

反射的原理在于Class对象

看一看程序加载的过程

aa3494d854c3fb73c32fbbc6f18fcb66.png

从图中大概可以看出反射是干什么用的了,那接下来就讲讲有关反射的其他方面

反射的API

反射API用来生成JVM中的类、接口或则对象的信息。

- Class类:反射的核心类,可以获取类的属性,方法等信息。

- Field类:Java.lang.reflec包中的类,表示类的成员变量,可以用来获取和设置类之中的属性值。

- Method类: Java.lang.reflec包中的类,表示类的方法,它可以用来获取类中的方法信息或者执行方法。

- Constructor类: Java.lang.reflec包中的类,表示类的构造方法。

下面就来讲讲怎么使用反射了

1.步骤

获取想要操作的类的Class对象

调用Class类中的方法

使用反射API来操作这些信息

2.获取Class对象的方法

//假设我们有一个Student类

方法一、(推荐)

Class clas= Class.forName("first.Student");//“”里写的是类的全路径

方法二、

Student stu= newStudent();

Class clas=stu.getClass();

方法三、

Class clas=Student.Class;

可以试试用两个不同的方法获取clas1和clas2,然后System.ou.println(clas1==clas2)看看会输出什么,原因在图上

3.获取构造方法、字段、main方法并调用

Student.java

public classStudent {publicString name;protected intage;charsex;privateString phoneNum;public static voidmain(String[] args) {

System.out.println("main方法执行了。。。");

}//---------------构造方法-------------------

Student(String str) {

System.out.println("(默认)的构造方法 s =" +str);

}//无参构造方法

publicStudent() {

System.out.println("调用了公有、无参构造方法执行了。。。");

}//有一个参数的构造方法

public Student(charname) {

System.out.println("姓名:" +name);

}//有多个参数的构造方法

public Student(String name, intage) {this.name=name;this.age=age;

System.out.println("姓名:" + name + "年龄:" + age);//这的执行效率有问题,以后解决。

}//受保护的构造方法

protectedStudent(boolean n) {

System.out.println("受保护的构造方法 n =" +n);

}//私有构造方法

private Student(intage) {

System.out.println("私有的构造方法 年龄:" +age);

}publicString toString() {return "Student [name=" + name + ", age=" + age + ", sex=" +sex+ ", phoneNum=" + phoneNum + "]";

}

}

Constructors.java(构造方法)

package first;

import java.lang.reflect.Constructor;public classConstructors {public static voidmain(String[] args) throws Exception {

Class clas=Class.forName("first.Student");

System.out.println("所有公有构造方法");

Constructor[] conArry=clas.getConstructors();for(int i=0;i

System.out.println(conArry[i]);

}

System.out.println("所有的构造方法");

conArry=clas.getDeclaredConstructors();for(int i=0;i

System.out.println(conArry[i]);

}

System.out.println("获取公有无参的构造方法");

Constructor con=clas.getConstructor(null);

System.out.println("con="+con);

Object obj=con.newInstance();

System.out.println("获取私有构造方法,并调用");

con=clas.getDeclaredConstructor(char.class);

System.out.println(con);//con.setAccessible(true);//暴力访问,针对private方法和字段时使用

obj=con.newInstance('a');//创建对象

}

}

输出

所有公有构造方法public first.Student(char)publicfirst.Student()public first.Student(java.lang.String,int)

所有的构造方法protectedfirst.Student(boolean)private first.Student(int)public first.Student(char)publicfirst.Student()

first.Student(java.lang.String)public first.Student(java.lang.String,int)

获取公有无参的构造方法

con=publicfirst.Student()

调用了公有、无参构造方法执行了。。。

获取私有构造方法,并调用public first.Student(char)

姓名:a

Fields.java(字段)

package first;

import java.lang.reflect.Field;public classFields {public static voidmain(String[] args)throws Exception {//TODO Auto-generated method stub

Class StuClass=Class.forName("first.Student");

System.out.println("获取所有公有的字段");

Field[] fieldArry=StuClass.getFields();for(Field f:fieldArry) {

System.out.println(f);

}

System.out.println("获取所有的字段(包括私有、受保护、默认的)");

fieldArry=StuClass.getDeclaredFields();for(Field f:fieldArry) {

System.out.println(f);

}

System.out.println("获取公有字段并调用");

Field f= StuClass.getField("name");

System.out.println(f);

Object obj=StuClass.getConstructor().newInstance();

StuClass.getConstructor(String.class,int.class).newInstance("a",10);

f.set(obj, "b");

Student stu=(Student)obj;

System.out.println(stu.name);

System.out.println("获取私有字段并调用");

f= StuClass.getDeclaredField("phoneNum");

System.out.println(f);

f.setAccessible(true);//暴力反射,解除私有限定

f.set(obj, "18888889999");

System.out.println("验证电话:" +stu);

}

}

输出

获取所有公有的字段publicjava.lang.String first.Student.name

获取所有的字段(包括私有、受保护、默认的)publicjava.lang.String first.Student.nameprotected intfirst.Student.agecharfirst.Student.sexprivatejava.lang.String first.Student.phoneNum

获取公有字段并调用publicjava.lang.String first.Student.name

调用了公有、无参构造方法执行了。。。

姓名:a年龄:10b

获取私有字段并调用privatejava.lang.String first.Student.phoneNum

验证电话:Student [name=b, age=0, sex=

Main.java

package first;

import java.lang.reflect.Method;public classMain {public static voidmain(String[] args) {try{//1、获取Student对象的字节码

Class clazz = Class.forName("first.Student");//2、获取main方法

Method methodMain= clazz.getMethod("main", String[].class);//第一个参数:方法名称,第二个参数:方法形参的类型,//3、调用main方法//methodMain.invoke(null, new String[]{"a","b","c"});//第一个参数,对象类型,因为方法是static静态的,所以为null可以,第二个参数是String数组//这里拆的时候将 new String[]{"a","b","c"} 拆成3个对象。。。所以需要将它强转。

methodMain.invoke(null, (Object) new String[] {});//方式一//methodMain.invoke(null, new Object[]{new String[]{"a","b","c"}});//方式二

} catch(Exception e) {

e.printStackTrace();

}

}

}

未完待续。。。。。

参考文章:

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值