在Java中的反射机制是指在运行状态中,对于任意一个类都能够知道这个类所有的属性和方法;并且对于任意一个对象,都能够调用它的任意一个方法;这种动态获取信息以及动态调用对象方法的功能成为Java语言的反射机制
反射使Java这种
静态编译型的语言具有了动态性。
反射具有看透类的能力,类的信息在反射面前都是透明的(包括private的属性和方法都是可以调用)。
Java反射机制主要提供一下功能:
1、在运行时判断任意一个对象所属的类。
2、在运行时构造任意一个类的对象。
3、在运行时判断任意一个类所具有的成员变量和方法。
4、在运行时调用任意一个对象的方法。
学习反射的意义:
反射使我们在编译的时候知道类型,而是延迟到运行时获得对象的属性调用对象的方法,是的java具有动态性。
Hibernate、Sping、MyBatis都是基于反射来实现的,可以说没有反射就没有这些框架。
类比学习一下:面向对象抽象过程
众多的人 ----> Person类
众多学生 -----> Stundent类
众多的类 -----> Class类:任何一个类里面都包含这些东西:Field[]、Constructor[]、Method[]
众多的属性 ------> Field类
众多构造方法 ------> Constructor类
众多的普通方法 ------> Method类
private String name;// Field
public Integer age;
class Field{
修饰符; //private
类型; //String
变量名字; // name
}
既然
Class
是描述类的类的类型
,那类结构里面包含哪些东西呢:
Field
、
Constructor
、
Method
,同样这些众多的属性、构造函数、方法也有对应的类类型表示他们。
Java.lang.Class;
Java.lang.reflect.Field;
Java.lang.reflect.Method;
Java.lang.reflect.Constructor;
对于类型的学习我们可以参考做
月饼的模子
,什么样模子就可以做出什么大小,图案的月饼。对于
Java
里面的
int
类型是四个字节,那么这个模子就是一个只能存放四个字节的模子,用这个模子做出来的就是
int
类型。同理
Class
、
Field
、
Method
、
Constructor
就分别是类、属性、方法、构造函数的模子。
通过
Class
可以获得类的所有属性Field[]、方法Method[]、构造方法Constructor[]信息。
通过
Field
可以获得属性的名字、类型、修饰符
通过
Method
可以获得方法的名字、参数、返回值。
Class:是反射的核心类
每个类加载到内存后,系统都会有唯一的一份
字节码对象
(Person.class/Student.class字节码对象都是Class这个类的实例)
public
void testClass()
throws ClassNotFoundException {
// 1.Class.forName(类路径)
Class
clazz1 = Class.
forName(
"com.situ.day15.Student");
// 2.类型.class
Class
clazz2 = Student.
class;
// 3.对象.getClass()
Student
student =
new Student();
Class
clazz3 =
student.getClass();
System.
out.println(
clazz1 ==
clazz2);
//true
System.
out.println(
clazz1 ==
clazz3);
//true
}
Constructor
的反射:
public
void testConstructor() {
Class
clazz = Student.
class;
Constructor[]
constructors =
clazz.getDeclaredConstructors();
for (
Constructor
constructor :
constructors) {
System.
out.println(
constructor);
System.
out.println(
constructor.getName());
//构造方法的名字
System.
out.println(
constructor.
getModifiers());
//修饰符
}
}
public com.situ.day15.Student()
com.situ.day15.Student
1
private com.situ.day15.Student(java.lang.String)
com.situ.day15.Student
2
@Test
public
void testConstructor2()
throws NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
Class
clazz = Student.
class;
//得到指定参数的构造方法
Constructor
constructor =
clazz
.getDeclaredConstructor(String.
class
);
System.
out.println(
constructor);
constructor.setAccessible(
true);
//加上之后就可以访问私有构造方法
//Student student1 = new Student("
zhansgan
");
Student
student = (Student)
constructor.newInstance(
"zhansgan");
System.
out.println(
student);
}
private com.situ.day15.Student(java.lang.String)
Student [name=zhansgan]
public
void testMethod()
throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
//Student student = new Student();
//student.setName("
lisi
");
Class
clazz = Class.
forName(
"com.situ.day15.Student");
//得到无参构造方法
Constructor
constructor =
clazz
.getConstructor();
//调用newInstance实例化对象
Student
student = (Student)
constructor.newInstance();
//student.setName("
lisi
");
Method
method =
clazz
.getMethod(
"setName"
, String.
class
);
method.invoke(
student,
"lisi");
System.
out.println(
student);
}
利用反射加配置文件加载指定数据库:
Hibernate/MyBatis
public
interface
class IDB {
public
abstract
void
getConnection();
}
public
class MySql implements IDB{
@Override
public
void
getConnection() {
System.
out.println(
"MySql.getConnection()");
}
}
public
class Oracle implements IDB{
@Override
public
void getConnection() {
System.
out.println(
"Oracle.getConnection()");
}
}
public
class SqlServer implements IDB{
@Override
public
void getConnection() {
System.
out.println(
"SqlServer.getConnection()");
}
}
public
class DBTest {
public
static
void main(String[]
args)
throws IOException, ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
//IDB
db
= new MySql();
//db.getConntion();
FileInputStream
fileInputStream =
new
FileInputStream(
"src/com/situ/day15/db/db.properties");
Properties
properties =
new Properties();
properties.load(
fileInputStream);
String
className =
properties.getProperty(
"className");
System.
out.println(
className);
Class
clazz = Class.
forName(
className);
//
Constructor
constructor =
clazz
.getConstructor();
//
IDB
db
= new MySql();
IDB
db = (AbstractDB)
clazz.newInstance();
db.getConntion();
}
}