文章目录
- 反射的基本概念
- 反射的概念
- 反射的作用
- 反射的基本信息
- 反射的相关类型
- Class类
- Class类中的相关方法
- newInstabce()
- getName方法
- Field类中的方法
- getFiled()方法
- getDeclareField(String name)
- Constructor类
- getConstructors()
- getDeclaredConstructors()
- Method类
- getMethods()
- getDeclaredMethod(String name, Class...<?> parameterTypes)
- 反射的优缺点
反射的基本概念
反射的概念
什么是反射呢?反射机制是在运行状态对于一个任意的类都能够知道这个类的所有属性和方法,对于任意的一个对象,都能够调用它的任意方法和属性,既然能够拿到那么,我们就可以进行修改部分类型的信息,这种动态获取信息以及动态调用对象的方法的功能称为java语言的反射机制。
这段话听起来生硬难懂,感觉难以理解,那么给大家翻译一下,其实反射就是java在运行的时候给自己开一个后门,我们都知道代码运行过程中我们的代码时不能进行修改的。可是一点办法都没吗?反射其实就是java给程序员开的一个后门。
反射的作用
- 反射相当于时程序员开的一个后门,我们在未来的开发中经常会遇到一些类他们的方法或者成员变量是私有的通过反射我们就可以使用这些私有的成员了。
- 反射最重要的还是底层框架开发比如在spring中,我们将所有的类Bean交给spring容器管理,无论是XML配置Bean还是注解配置,当我们从容器中获取Bean来依赖注入时,容器会读取配置,而配置中给的就是类的信息,spring根据这些信息,需要创建那些Bean,spring就动态的创建这些类。
反射的基本信息
在java程序中许多对象在运行时会出现两种类型运行时类型和RTI编译时类型,类如Person p=new student();这句代码中p在编译时类型为person在运行时类型是student,程序需要在运行时发现对象和类的真实信息。而通过反射程序就能判断出该对象和类属于哪些类。
反射的相关类型
类名 | 用途 |
---|---|
Class类 | 代表类的实体在运行的java程序中表示类和接口 |
Field类 | 代表类的成员变量/类的属性 |
Method类 | 代表类的方法 |
Constructor类 | 代表类的构造方法 |
Class类
代表类的实体在运行的java程序中表示类和接口java文件被编译后会形成一个。class的字节码文件,jvm此时就要去解读.class文件,被编译过后的java文件,class也被jvm解析为一个对象,这个对象就是java.lang.Class这样当程序在运行时每个java文件最终变成了Class类对象的一个实例,我们通过java的反射机制应用道这个实例,就可以去获得甚至去添加改变这个类的属性和动作,使得这个类变成一个动态的类。
Class类中的相关方法
方法 | 用途 |
---|---|
getClassLoadar() | 获取类的加载器 |
getDeclaredClasses() | 返回一个数组数组中包含了所有类和接口类的对象(包括私有的) |
forName(String className) | 根据类名返回类的对象 |
newlnstance() | 创建类的实例 |
getName() | 获得类的完整路径名字 |
forName用法
public static void main(String[] args) {
try {
Class<?> cl=Class.forName("Student");
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
这里的forName根据类名返回Class类的对象这个forName有什么作用呢?其实就是实例出一个Class的对象便于我们后期的使用,因为接下来我们想要实列化出相应的对象就需要此时实例出的cl这里我们也需要一个列子就是Student类
public class Student {
//---------------构造方法-------------------
//(默认的构造方法)
Student(String str){
System.out.println("(默认)的构造方法 s = " + str);
}
//无参构造方法
public Student(){
System.out.println("调用了公有、无参构造方法执行了。。。");
}
//有一个参数的构造方法
public Student(char name){
System.out.println("姓名:" + name);
}
//有多个参数的构造方法
public Student(String name ,int age){
System.out.println("姓名:"+name+"年龄:"+ age);//这的执行效率有问题,以后解决。
}
//受保护的构造方法
protected Student(boolean n){
System.out.println("受保护的构造方法 n = " + n);
}
//私有构造方法
private Student(int age){
System.out.println("私有的构造方法 年龄:"+ age);
}
public void show1(){
System.out.println("show");
}
public int age;
public String name;
private String classmate;
}
newInstabce()
使用newInstabce方法可以创建类的实例,但是要注意这个方法返回的是一个Object对象我们需要进行类型转化代码如下
public static void main(String[] args) {
try {
Class<?> cl=Class.forName("Student");
Student se= (Student) cl.newInstance();
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}catch (Exception e){
System.out.println(e.fillInStackTrace());
}
}
getName方法
该方法可以获得类的完整路径名称用法如下
public static void main(String[] args) {
try {
Class<?> cl=Class.forName("Student");
Student se= (Student) cl.newInstance();
String packagename=cl.getName();
System.out.println(packagename);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}catch (Exception e){
System.out.println(e.fillInStackTrace());
}
}
Field类中的方法
方法名称 | 作用 |
---|---|
getFiled(String Name) | 获得某个公有的属性 |
getFileds() | 获得公有的属性对象 |
getDeclaredField(String name) | 获得某个属性的对象 |
getDeclaredFields() | 获得所有属性的对象 |
getFiled()方法
getFiled(String Name)可以获得某个公有属性。用法如下
public static void main(String[] args) {
try {
Class<?> cl=Class.forName("Student");
Student se= (Student) cl.newInstance();
Field fe=cl.getField("name");
System.out.println(fe);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}catch (Exception e){
System.out.println(e.fillInStackTrace());
}
}
getDeclareField(String name)
此方法可以获得任意属性,其中也包括了私有属性使用如下
public static void main(String[] args) {
try {
Class<?> cl=Class.forName("Student");
Student se= (Student) cl.newInstance();
Field fe=cl.getField("name");
System.out.println(fe);
Field fe2=cl.getDeclaredField("classmate");
System.out.println(fe2);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}catch (Exception e){
System.out.println(e.fillInStackTrace());
}
}
Constructor类
方法 | 作用 |
---|---|
getConstructor(Class…<?> parameterTypes) | 获得该类中与参数类型匹配的公有构造方法 |
getConstructors() | 获得该类的所有公有构造方法 |
getDeclaredConstructor(Class…<?> parameterTypes) | 获得该类中与参数类型匹配的构造方法 |
getDeclaredConstructors() | 获得该类所有构造方法 |
getConstructors()
获得该类中所有的公有构造方法
public static void main(String[] args) {
try {
Class<?> cl=Class.forName("Student");
Constructor[] se2=cl.getConstructors();
for (Constructor neq:se2) {
System.out.println(neq);
}
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}catch (Exception e){
System.out.println(e.fillInStackTrace());
}
}
getDeclaredConstructors()
获取所有的的构造方法包括私有的公有的等
public static void main(String[] args) {
try {
Class<?> cl=Class.forName("Student");
Constructor[] se2=cl.getConstructors();
for (Constructor neq:se2) {
System.out.println(neq);
}
System.out.println("___________________________");
se2=cl.getDeclaredConstructors();
for (Constructor se3:se2) {
System.out.println(se3);
}
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}catch (Exception e){
System.out.println(e.fillInStackTrace());
}
}
Method类
方法 | 作用 |
---|---|
getMethod(String name, Class…<?> parameterTypes) | 获得该类某个公有的方法 |
getMethods() | 获得该类所有公有的方法 |
getDeclaredMethod(String name, Class…<?> parameterTypes) | 获得该类 |
getDeclaredMethods() | 获得该类所有方法 |
getMethods()
该方法可以获得该类中所有的公有方法
public static void main(String[] args) {
try {
Class<?> cl=Class.forName("Student");
Method[] me=cl.getMethods();
for (Method me2:me) {
System.out.println(me2);
}
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}catch (Exception e){
System.out.println(e.fillInStackTrace());
}
getDeclaredMethod(String name, Class…<?> parameterTypes)
该方法可以获取某个方法这里两个参数要输入的内容是方法名称以及其形参类型
public static void main(String[] args) {
try {
Class<?> cl=Class.forName("Student");
Method[] me=cl.getMethods();
Method me2=cl.getDeclaredMethod("show1",String.class);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}catch (Exception e){
System.out.println(e.fillInStackTrace());
}
反射的优缺点
优点:
-
对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法
-
增加程序的灵活性和扩展性,降低耦合性,提高自适应能力
-
反射已经运用在了很多流行框架如:Struts、Hibernate、Spring 等等。
缺点: -
使用反射会有效率问题。会导致程序效率降低。具体参考这里
-
反射技术绕过了源代码的技术,因而会带来维护问题。反射代码比相应的直接代码更
努力做好吧