1.java 的动态性包括:
反射机制,动态编译,动态执行JavaScript,动态字节码的操作;
2.动态语言:
Java可以被称之为 准动态语言;
3. reflection :
4.Class 这个类:
5.获得 class 对象的方法:
package Test;
/**
*
* 用来测试获取class对象的类
*
* @author Wang
*
*/
public class Students {
private int id;
private String name;
private String sex;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public Students(int id, String name, String sex) {
super();
this.id = id;
this.name = name;
this.sex = sex;
}
public Students (){
}
}
package Test;
/**
*
* 我们来测试反射中class对象的获取方法
* 和各个类的class对象是相同
*
* @author Wang
*
*/
public class getClass {
public static void main (String[] args){
/*
* 获得类的class对象 的三种方法
*/
//路径应该是报名 加上 类名
String path = "Test.Students";
//这个获取class对象的方法是我们最常用的
//因为这个很适用于我们自己写的类 因为我们自己写的类的路径我们都知道
//获取class对象的作用是我们可以通过这个对象获取类的全部信息
try {
//第一种方法
Class class1 = Class.forName(path);
//第二种方法
Class class2 = String.class;
Class class3 = String.class;
//在这里我们会发现2和3的hashCode值一样 因为一个类只会被反射出来一次;
System.out.println(class2.hashCode());
System.out.println(class3.hashCode());
//第三种方法
int arr1[] = new int[10];
int arr2[] = new int[20];
double arr3[] = new double[10];
int arr4[][] = new int[10][10];
//数组的类型和维数会影响反射出来的类对象,但是数组的元素个数赎不回影响的
System.out.println(arr1.getClass().hashCode());
System.out.println(arr2.getClass().hashCode());
System.out.println(arr3.getClass().hashCode());
System.out.println(arr4.getClass().hashCode());
} catch (Exception e) {
e.printStackTrace();
}
}
}
5.反射机制的作用:
Topic 1 : 我们用反射API 获取类信息(名字、属性、方法、构造器等) 还与上面的那个students连接 ;
代码如下:
package Test;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
/**
*
* 我们用反射API 获取类信息(名字、属性、方法、构造器等)
*
* @author Wang
*
*/
public class Demo02 {
public static void main(String[] args){
String path = "Test.Students";
try {
Class class1 = Class.forName(path);//获得类对象
/**
* 获得类的名字
*/
//获得类的全名 带路径的 : Test.Students
System.out.println(class1.getName());
//获得类的名字 只有一个名字 : Students
System.out.println(class1.getSimpleName());
/**
* 获得类的属性信息
*/
//这个是获得全部的public属性
Field fields[] = class1.getFields();
//打印他的全部的public属性 : public int Test.Students.hight
for(Field temp : fields)
System.out.println(temp);
//获得他全部的声明过的属性
Field[] fields1 = class1.getDeclaredFields();
//打印他的全部属性
for(Field temp : fields1)
System.out.println(temp);
//获取指定的属性
Field f = class1.getDeclaredField("name");
/**
* 获取方法信息
*/
//public
Method[] methods = class1.getMethods();
//所有的
Method[] methods1 = class1.getDeclaredMethods();
//指定的
Method m01 = class1.getDeclaredMethod("getName", null);
//如果方法有参,则必须传递参数类型对应的class对象
Method m02 = class1.getDeclaredMethod("setName", String.class);
for(Method temp : methods1){
System.out.println("方法:"+ temp);
}
/**
* 获得构造器信息
*/
//获得无参构造
Constructor constructor = class1.getConstructor();
System.out.println("获得无参构造器:"+ constructor);
//获得所有的构造器
Constructor[] constructors = class1.getDeclaredConstructors();
//获得带参特定的构造器
Constructor c = class1.getDeclaredConstructor(int.class,String.class,String.class);
System.out.println("获得带参特定构造器:"+ c);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Topic 2 :
我们利用反射来动态操作类的信息;
代码如下:
package Test;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
/**
*
* 我们通过反射的API,来动态的操作:类的信息(属性,方法,构造器等)
*
* @author Wang
*
*/
public class Demo03 {
public static void main(String[] args){
String path = "Test.Students";
try {
/**
* 这里必须用泛型说明他是Students 类型的Class 不然下面没法执行
* Students s = class1.newInstance();
*/
Class <Students> class1 = (Class <Students> ) Class.forName(path);
//通过反射API 调用构造方法来构造对象
//其实这里调用的是无参构造函数
Students s = class1.newInstance();
//System.out.println(s);
//这里调用的是有参构造函数 同样的要加泛型
Constructor <Students> c = class1.getConstructor(int.class,String.class,String.class);
Students s2 = c.newInstance(1606955,"wangtong","男");
//通过反射调用方法 注意我们字符串参数要加双引号的
Students s3 = class1.newInstance();
/*
* 这两行的作用就是 u3.setId(1234); 而他的好处就是可以从别传过来
* (从数据库里传过来 从浏览器中传过来)实现动态的调用
*/
Method m = class1.getMethod( "setId" , int.class);
m.invoke(s3,1234);
//通过反射来操作属性
Students s4 = class1.newInstance();
//注意私有属性 你看看是怎么写的
Field f = class1.getDeclaredField("name");
/*
* f.set(s4, "wangtong" );
* 这一句运行的时候会报错 外面的方法是无法修改私有属性
* 解决方法如下:
*/
f.setAccessible(true); //设置这个属性不需要做安全检查了,可以直接访问
f.set( s4 , "wangtong"); //通过反射直接写属性
System.out.println(s4.getName()); //直接使用get方法来得到属性的值
System.out.println(f.get(s4)); //通过反射直接读属性的值
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}