动态语言
——程序在运行的时候可以改变程序的结构或者变量类型,典型的语言:javascript,pyhton,ruby。
如下面这段javascript代码:
function test(){
var a=3;
var b=4;
alert(a+b);
}
C,C++,java并不是动态语言,但是java具有一定的动态性,我们可以通过反射机制或者字节码的操作获得类型动态语言的特性,java的动态性让java编程更加的灵活!
1 —— java的反射机制 reflection
反射的意思就是程序在运行期间动态的获取类中的属性,包括包括其modifiers(修饰符),fields(属性),methods(方法),Annotation(注解),那么什么叫动态的获取呢?
在类加载的时候,jvm会给每个类的创建一个Class类型的类对象(一个类只产生一个类对象),而这个类对象中包含类的全部信息,我们就可以通过这个类对象获得类的全部结构。这个对象就好像是一面镜子,透过这个镜子可以看到类的结构,这就称之为反射!
2 —— 反射的三种方式
Class clazz= Class.forName(""); //参数为类的全路径
类名.class
对象.getClass
3 —— 反射机制的常见作用
反射获取到了类的class对象,那么它到底应该怎么使用呢?
首先我们创建一个类
public class Student {
private String name;
private String age;
private String sex;
public Student() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public Student(String name,String age,String sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
public void study() {
System.out.println("学生学习");
}
}
再创建一个测试类
package com.turing.test.jdbc;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class Demo02 {
public static void main(String[] args) throws Exception {
testField();
testConstructor();
testMethod();
}
/**
* 测试反射获取属性
*/
public static void testField() throws Exception{
//第一种反射获取class对象
Class clazz = Class.forName("com.turing.test.jdbc.Student");
//获得他的全部属性
Field[] fileds = clazz.getDeclaredFields();
//获得他指定的属性
Field name = clazz.getDeclaredField("name");
System.out.println(name);
}
/**
* 测试反射获取构造方法
*/
public static void testConstructor() throws Exception{
//第二种反射获取class对象
Class clazz = com.turing.test.jdbc.Student.class;
//获得他的全部的构造器
Constructor[] constructors = clazz.getDeclaredConstructors();
//获得他的无参构造器
Constructor constructorNoParameter = clazz.getDeclaredConstructor(null);
System.out.println(constructorNoParameter);
//获得他的有参构造器
Constructor constructor = clazz.getDeclaredConstructor(String.class,String.class,String.class);
System.out.println(constructor);
System.out.println(constructor.getParameterCount());//参数个数
}
/**
* 测试反射获取方法
*/
public static void testMethod() throws Exception {
//第三种反射获取class对象
Student stu = new Student();
Class clazz = stu.getClass();
//获取全部的方法
Method[] methods = clazz.getDeclaredMethods();
//获得某个指定的方法
Method method = clazz.getDeclaredMethod("study", null);
System.out.println(method);
}
}
第二个测试类
package com.turing.test.jdbc;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
/**
* 反射实例化对象
* @author lvdefu
*
*/
public class Demo03 {
public static void main(String[] args) throws Exception {
testReflection();
}
@SuppressWarnings("all")
public static void testReflection() throws Exception {
Class<Student> clazz = (Class<Student>) Class.forName("com.turing.test.jdbc.Student");
//反射获取他的实例化对象
Student stu = clazz.newInstance(); //这个方法默认调用它的无参构造器
//反射调用有参数的构造方法
Constructor<Student> constructor = clazz.getDeclaredConstructor(String.class,String.class,String.class);
Student stu1 = constructor.newInstance("LDF","28","男"); //调用有参数构造器
System.out.println("名字:"+stu1.getName()+"年龄:"+stu1.getAge()+"性别:"+stu1.getSex());
//通过反射API调用方法
Student stu2 = clazz.newInstance();
Method setNameMethod = clazz.getDeclaredMethod("setName",String.class);
setNameMethod.invoke(stu2, "GH");//invoke 代表激活这个方法
Method getNameMethod = clazz.getDeclaredMethod("getName", null);
String a = (String)getNameMethod.invoke(stu2, null);
System.out.println(a);
//通过反射API设置他的属性
Student stu3 = clazz.newInstance();
Field f = clazz.getDeclaredField("name");
//设置私有制属性权限的验证
f.setAccessible(Boolean.TRUE);
//设置他属性的值
f.set(stu3, "BWT");
//第一种获取值方法
System.out.println(stu3.getName());
//通过反射读取属性的值
System.out.println(f.get(stu3));
}
}