反射
想必大家都听过一句话,框架=注解+反射+设计模式,由此可见反射的重要性。
什么是反射?
我的理解是:
Java应用程序运行的步骤是:①由javac.exe将.java文件编译成.class文件 ②由java.exe将.class字节码文件解释运行。反射就是通过内存中的.class文件对象获取该类的内部结构,并且可以创建该类的实例,调用此对象的属性和方法。
怎么使用反射?就需要使用到Java.lang.Class类
Class类的对象可以是:①类②接口③枚举④数组⑤注解⑥基本数据类型⑦void
@Test
public void test5() {
// Class类的对象可以是:①类②接口③枚举④注解⑤数组⑥基本数据类型⑦void
Class c1=Student.class;
Class c2=Serializable.class;
Class c3=ElementType.class;
Class c4=int [].class;
Class c5=String [][].class;
Class c6=Override.class;
Class c7=int.class;
Class c8=void.class;
// 只要数据类型一致并且都是相同维度,则对应的Class对象也一样
int [] arr=new int [10];
int [] arr1=new int [10];
Class c9=arr.getClass();
Class c10=arr1.getClass();
System.out.println(c9==c10);
String [][] str=new String [10][];
String [][] str1=new String [11][];
Class c11=str.getClass();
Class c12=str1.getClass();
System.out.println(c11==c12);
}
Class类获取实例是运行时行为,动态性的
@Test
public void test7() throws Exception {
// 类加载是个运行时行为,动态的
int num=new Random().nextInt(3); // 0 1 2
switch(num) {
case 0:
String str=(String) getInstance("java.lang.String");
System.out.println(str.toString());
break;
case 1:
Date date=(Date)getInstance("java.util.Date");
System.out.println(date.toString());
break;
case 2:
Student s=(Student)getInstance("reflect.Student");
System.out.println(s.toString());
break;
}
}
public Object getInstance(String clathPath) throws Exception {
Class clazz=Class.forName(clathPath);
return clazz.getConstructor(null).newInstance(null);
}
1.Class类的实例化的三种方式:①类名.class ②对象.getClass() ③Class.forName("全限定类名") :最常用 ④使用类加载器
由于.class文件在内存中的对象就存在一份,所以三种方式实例化的对象都指向相同地址。
//Student类对应的Class类对象,在内存中只有一份。 当我们new Student()去创建一个实例时,jvm就会在磁盘中查找Student.class文件,并将其加载到内存中,一个类对应一个Class对象
//Class对象的实例化的三种方式
// 1.类名.class
Class clazz = Student.class;
System.out.println(clazz);
// 2.对象.getClass()
Class clazz1=new Student().getClass();
System.out.println(clazz1);
System.out.println(clazz==clazz1);
// 3.Class.forName("全限定类名") :这种方式最常用
Class clazz2=Class.forName("reflect.Student");
System.out.println(clazz2);
System.out.println(clazz==clazz2);
// 4.使用类加载器
ClassLoader loader=ReflectionTest.class.getClassLoader();
Class clazz3=loader.loadClass("reflect.Student");
System.out.println(clazz3);
System.out.println(clazz==clazz3);
2.获取当前运行时类的构造器
package reflect;
import java.io.Serializable;
import java.util.Comparator;
public class Student {
public int id;
protected String name;
String major;
private char sex;
public Student() {
super();
System.out.println("public Student()");
}
protected Student(int id, String name) {
super();
this.id = id;
this.name = name;
}
Student(int id, String name, String major) {
super();
this.id = id;
this.name = name;
this.major = major;
}
private Student( String name) {
super();
this.name = name;
}
public Student(int id, String name, String major, char sex) {
super();
this.id = id;
this.name = name;
this.major = major;
this.sex = sex;
}
@Override
public java.lang.String toString() {
return "Student [id=" + id + ", name=" + name + ", major=" + major + ", sex=" + sex + "]";
}
}
getConstructors():获取当前运行时类的所有public权限的构造器
getDeclaredConstructors():获取当前运行时类的所有权限的构造器
@Test
public void test2() throws Exception {
// 通过反射获取构造器
Class clazz=Class.forName("reflect.Student");
//getConstructors():获取当前运行时类中的public构造器
Constructor [] cons=clazz.getConstructors();
for(Constructor c:cons) {
System.out.print(c+"\t");
}
System.out.println();
//getDeclaredConstructors():获取当前运行时类的所有权限的构造器
Constructor [] cons1=clazz.getDeclaredConstructors();
for(Constructor c:cons1) {
System.out.print(c+"\t");
}
System.out.println();
//通过反射获取当前运行时类的实例
// 1.调用newInstance():调用当前运行时类的无参构造器
clazz.getConstructor().newInstance();
// 2.通过调用getDeclaredConstructor():获取所有权限的构造器
Constructor c=clazz.getDeclaredConstructor(int.class,java.lang.String.class,java.lang.String.class,char.class);
Student s=(Student)c.newInstance(1001,"小明","英语",'男');
System.out.println(s.toString());
// 获取私有属性的构造器
Constructor c1=clazz.getDeclaredConstructor(java.lang.String.class);
c1.setAccessible(true);
Student s1=(Student)c1.newInstance("小付");
System.out.println(s1);
}
3. 获取当前运行时类的属性
getFields():获取当前运行时类以及父类的所有public属性
getDeclaredFields():获取当前运行时类的所有权限的属性
public class Person<T> {
public int age;
protected String NickName;
double height;
private double weight;
public void info() {
System.out.println("我是一个人");
}
}
public class Student extends Person{
public int id;
protected String name;
String major;
private char sex;
public Student() {
super();
System.out.println("public Student()");
}
protected Student(int id, String name) {
super();
this.id = id;
this.name = name;
}
Student(int id, String name, String major) {
super();
this.id = id;
this.name = name;
this.major = major;
}
private Student( String name) {
super();
this.name = name;
}
public Student(int id, String name, String major, char sex) {
super();
this.id = id;
this.name = name;
this.major = major;
this.sex = sex;
}
@Override
public java.lang.String toString() {
return "Student [id=" + id + ", name=" + name + ", major=" + major + ", sex=" + sex + "]";
}
}
@Test
public void test3() throws Exception {
Class clazz=Class.forName("reflect.Student");
//getFields():获取当前运行时类以及父类的所有public属性
Field [] fields=clazz.getFields();
for(Field f:fields) {
System.out.print(f+"\t");
}
System.out.println();
//getDeclaredFields():获取当前运行时类的所有权限的属性
Field [] fs=clazz.getDeclaredFields();
for(Field f:fs) {
System.out.print(f+"\t");
}
System.out.println();
//调用getDeclaredField(参数1):参数1为属性名,获取属性
//为某个对象属性赋值:set(obj,value)
Student s=(Student)clazz.getConstructor().newInstance();
Field field=clazz.getDeclaredField("name");
field.set(s, "小明");
System.out.println(s.toString());
}
4.获取当前运行时类的非静态方法
getDeclaredMethod(参数1,参数2):获取当前运行时类的方法
参数1:方法名 参数2:方法参数
private void info(String name) {
System.out.println("我是一名叫做"+name+"的学生");
}
@Test
public void test4() throws Exception {
Class clazz=Class.forName("reflect.Student");
//getMethods():获取当前运行时类以及父类的public方法
Method [] ms=clazz.getMethods();
for(Method method:ms) {
System.out.println(method);
}
System.out.println("**********************");
//getDeclaredMethods():获取当前运行时类的所有权限的方法
Method [] mes=clazz.getDeclaredMethods();
for(Method method:mes) {
System.out.println(method);
}
System.out.println("************************");
//getDeclaredMethod(参数1,参数2):参数1为方法名,参数2为方法的参数
Method method=clazz.getDeclaredMethod("info",String.class);
method.setAccessible(true);
method.invoke(clazz.getConstructor().newInstance(null), "小明");
}
Properties使用的两种方式:
@Test
public void test6() throws IOException {
//方法1:默认的路径是当前项目下的路径
Properties properties=new Properties();
// FileInputStream fis=new FileInputStream("jdbc.properties");
// properties.load(fis);
// System.out.println("username = "+properties.getProperty("uerName")+" password = "+properties.getProperty("passWord"));
//方法2:默认的路径是当前项目下的src下的路径
ClassLoader loader=ReflectionTest.class.getClassLoader();
InputStream is=loader.getResourceAsStream("jdbc.properties");
properties.load(is);
System.out.println("username = "+properties.getProperty("uerName")+" password = "+properties.getProperty("passWord"));
}