首页 > 编程语言 >java web开发(反射)

java web开发(反射)

时间:2022-11-23 15:04:35浏览次数:33  
标签:web java 反射 System println return cls Class out

        反射是java很重要的一个特点。也是它区别于c、c++、fortan等传统语言的一个重要的语言特征。通过反射可以做很多的事情,比如动态创建类,动态修改变量,动态调用类函数等等。spring等一些框架,也大量使用了java的反射特性。

        反射特性的基础是数据类型。java编译器默认为所有的class创建了一个数据类型,那就是Class。如果不好理解,可以看成是c++里面的typeinfo。下面,可以通过几个test case验证下。

1、添加必要的引用文件

import java.lang.*;
import java.lang.reflect.*;

2、准备测试类

class Person {
public String name;

public String getName(){
return "Person";
}
}

class Student extends Person{
public int score;
private int grade;

public Student(){
return;
}

public Student(int s, int g){
score = s;
grade = g;
}

public int getScore() {
return 10;
}

private int getGrade(){
return 100;
}
}

3、测试1,验证Class的存在

public static void test1() {
System.out.println(String.class);
}

        这个例子比较简单,主要是验证一下是不是真的有Class存在。如代码所示,首先获取了String数据类型的Class,接着就是将这个Class打印出来。运行,不出意外,你就会看到这样的内容,

class java.lang.String

4、测试2,判断一个实例的数据类型是否正确

public static void test2() {

Class s1 = String.class;

String s = "abc";
Class s2 = s.getClass();

if(s1 == s2){
System.out.println("yes");
}else{
System.out.println("no");
}
}

        前面已经了解到数据类型确实是存在的。那么,接下来就可以判断,假设存在一个实例,可以检验下它是否真的属于某种数据类型。如上面所示,首先获取了String的数据类型s1,接着有一个实例s,同样可以获取它的数据类型s2,后面就可以判断s1和s2是否相等。相等,则输出yes;否则,输出no。不出意外的话,输出的结果肯定是yes。

5、测试3,通过名称获取数据类型

public static void test3() {
try {
Class cls = Class.forName("java.lang.String");
String s = "abc";
if (cls == s.getClass()) {
System.out.println("yes");
} else {
System.out.println("no");
}
} catch (ClassNotFoundException e){
return;
}
}

        测试3和测试2的代码非常相像。唯一的区别,这里获取初始数据类型的方法不再是String.class,而是通过Class.forName来获取。其实结果都是一样的。

6、测试4,通过obj获取数据类型

public static void test4(){
Object obj = new String("abc");
Class cls = obj.getClass();
System.out.println(cls);
}

        Object是所有类的父类。假设创建一个String对象,将它赋值给obj。再从obj获取Class,赋值给cls,那么这个时候如果打印cls的话,本质上和String.class的打印结果是一样的。

7、测试5,通过class创建实例

public static void test5(){
Class cls = String.class;
try {
String s = (String) cls.newInstance();
}catch(InstantiationException ins){
return;
}catch(IllegalAccessException ill){
return;
}
}

        java语言的发明人设计发射这一特性,绝不仅仅用来实现打印这么简单。通过这个Class,是可以直接调用newInstance创建实例的。当然,创建的过程中需要处理一下InstantiationException和IlegalAccessException这两个异常。当然,这里创建实例的时候,没有带参数。后面会接着讨论,如果需要构造函数带参数,应该怎么来处理。

8、测试6,访问类变量

public static void test6() {
Class cls = Student.class;

try {
System.out.println(cls.getField("score"));
System.out.println(cls.getField("name"));
System.out.println(cls.getDeclaredField("grade"));

Field f = cls.getField("score");
System.out.println(f.getName());
System.out.println(f.getType());

Student s = new Student();
s.score = 10;

try {
Object o = f.get(s);
System.out.println(o);
f.set(s, 100);

o = f.get(s);
System.out.println(o);

}catch(IllegalAccessException ill){
return;
}

}catch(NoSuchFieldException no){

return;
}
}

        有了数据类型Class,就可以获取类里面的变量信息,使用getField子函数就可以实现这一目的。不仅如此,拿到了field信息,就可以通过getName获取名称信息,通过getType获得数据信息。更进一步的话,可以通过get获取数据,通过set设置数据,这都是做得到的。

9、测试7,访问类函数

public static void test7(){

Class cls = Student.class;

try {
System.out.println(cls.getMethod("getScore"));
System.out.println(cls.getMethod("getName"));
}catch (NoSuchMethodException no){
return;
}

try {
System.out.println(cls.getDeclaredMethod("getGrade"));
}catch (NoSuchMethodException no){
return;
}

Student s = new Student();

try {
Method m = Student.class.getMethod("getScore");

try {
System.out.println(m.invoke(s));
}catch(IllegalAccessException ill){
return;
}catch(InvocationTargetException invo){
return;
}
}catch(NoSuchMethodException no){
return;
}
}

        既然类变量可以通过Class访问,那么类函数也不例外。类函数的获取方法是getMethod,返回值是Method。有了这个Method,接下来就可以调用invoke函数,直接获得数据结果了。是不是很神奇?当然,执行的过程中还要处理IllegalAccessException和InvocationTargetException两个异常/

10、测试8,类构造

public static void test8(){

try {
Constructor cons = Student.class.getConstructor(int.class, int.class);

try {
Student s = (Student) cons.newInstance(1, 2);
System.out.println(s.score);

}catch(InstantiationException ins){
return;
}catch(IllegalAccessException ill){
return;
}catch(InvocationTargetException invo){
return;
}

}catch(NoSuchMethodException no){
return;
}
}

        类构造是Class特征中的重中之重。有了这一点,类的构造不需要用户自己来显式完成了。如果设计好合适的框架,完全可以通过Class来完成,不需要用户的参与。类构造的完成,主要是通过Class的getConstructor来实现的。获取到Constructor之后,就可以调用它的newInstance来完成了。这和测试5有点类似,不过它当时没有带参数。

11、测试9,查找继承关系

public static void test9(){

Class chd = Student.class;
Class parent = chd.getSuperclass();
Class grnd = parent.getSuperclass();

System.out.println(chd);
System.out.println(parent);
System.out.println(grnd);

}

        Class还有一个用的比较多的特征,就是查找继承关系。这在一些场景下也是非常有用的。比如说,如果我们想调用某个类的虚函数,那么就要先判断下,这个类是不是真的来自于某个父类,这样才好进行后面的操作。

        文章读到这里,基本上应该有点头昏眼花了。有兴趣的同学可以把这部分内容反复看看,还是很有意思的。反射和注解算是java比较有特色的两个特征,值得好好学学。当然后续的语言,比如c#,其实也包含了这两点,当然这都是后话了。

标签:web,java,反射,System,println,return,cls,Class,out
From: https://blog.51cto.com/feixiaoxing/5881296

相关文章

  • java web开发(IDEA安装 + 第一个java工程)
    发环境是myeclipse。时过境迁,现在大家更多地愿意用IDEA环境来开发。对于新手,尤其是刚入门的同学来说,有一个好的IDE环境还是能够减轻不少负担的。这样,可以让学习的曲线不是......
  • 常用js库和框架(vue&element ui与webpy)
        编写前端代码的同学都知道,目前最火的前端代码是vue&elementui,而后端个人又比较喜欢用webpy,那么这两者是怎么配合的。现在都说要实现前后端分离,两者的json数据......
  • java上位机开发(编译和部署)
        之前开发java程序的时候,一直用的是命令行来完成的。其实大家也可以用eclipse、IDEA这些工具来做。部署也是一样,一方面大家可以用maven这些工具来完成,另外一方面......
  • java和设计模式(行为模式)
        和构建模式、结构模式相比较,行为模式的内容要多一些。在设计模式中,行为模式强调的是类和对象之间的交互关系。它更多强调的是,在特定的行为场景种,使用哪一种设计......
  • java和设计模式(结构模式)
        在设计模式中,有一类设计模式是比较有意思的,但是关注的人不多。这就是结构模式。如果说创建模式的重点是如何创建出实例对象,那么结构模式的特点就是利用类、示例......
  • java和设计模式(创建模式)
        有过软件开发经验的同学都知道,软件开发功能怎么都能完成。但是如果需要在软件上面不断做需求变更和重构,这就变得好复杂了。对于这些变更,如果只是硬编码去解决,那......
  • java上位机开发(定时器使用)
    在实际开发中,我们发现有一些任务需要周期性的完成,比如说数据库的检查、设备的检查、状态的检查、变量的检查等等。这个时候就会使用到定时器。在javaswing中,因为本身已经集......
  • java.lang.ClassNotFoundException: org.apache.commons.pool2.impl.GenericObjectPoo
    启动连接redis时报错因为spring-boot-starter-data-redis升级后将commons-pool2踢出去了解决方式两个1.导入commons-pool2依赖<dependency><groupId>org.apach......
  • FR11 webservice程序数据集
    packagecom.fr.data;importcn.hutool.core.lang.Console;importcn.hutool.http.webservice.SoapClient;importcn.hutool.json.JSONArray;importcn.hutool.json.......
  • 按键精灵字库文件点阵图显示Java代码
    如题:publicclassTest{publicstaticvoidmain(String[]args){Strings="01800B0200F40C07181870300300000020C000C303030C0C0C303030C0C0E30303E......