Java Web知识点【3】

本文深入讲解Java反射机制,包括Class、Constructor、Method和Field等核心概念及其应用实践。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

反射概述

 

1 反射的概述

1.1 什么是反射

每个.class文件被加载到内存后都是一个Class类的对象!例如Demo.class加载到内存后它是Class<Demo>类型的一个对象。


反射就是通过Class对象获取类型相关的信息。一个Class对象就表示一个.class文件,可以通过Class对象获取这个类的构造器、方法,以及成员变量等。

反射是Java的高级特性,在框架中大量被使用!我们必须要了解反射,不然无法学好JavaWeb相关的知识!

 

1.2 反射相关类

与反射相关的类:

l Class:表示类;

l Field:表示成员变量;

l Method:表示方法;

l Constructor:表示构造器。

 

2. Class

 

2.1 获取Class

获取Class类的三种基本方式:

l 通过类名称.class,对基本类型也支持;

Ø Class c = int.class

Ø Class c = int[].class

Ø Class c = String.class

l 通过对象.getClass()方法

Ø Class c = obj.getClass();

l Class.forName()通过类名称加载类,这种方法只要有类名称就可以得到Class

Ø Class c = Class.forName(“cn.itcast.Demo”);

 

2.2Class类的常用方法

l String getName():获取类名称,包含包名;

l String getSimpleName():获取类名称,不包含包名;

l Class getSupperClass():获取父类的Class,例如:new Integer(100).getClass().getSupperClass()返回的是Class<Number>!但new Object().getSupperClass()返回的是null,因为Object没有父类;

l T newInstance():使用本类无参构造器来创建本类对象;

 

l boolean isArray():是否为数组类型;

l boolean isAnnotation():是否为注解类型;

l boolean isAnnotationPresent(Class annotationClass):当前类是否被annotationClass注解了;

l boolean isEnum():是否为枚举类型;

l boolean isInterface():是否为接口类型;

l boolean isPrimitive():是否为基本类型;

l boolean isSynthetic():是否为引用类型;

 

2.3 通过反射创建对象

public class Demo1 {

@Test

public void fun1() throws Exception {

String className = "cn.itcast.User";

Class clazz = Class.forName(className);

User user = (User)clazz.newInstance();

System.out.println(user);

}

}

 

class User {

private String username;

private String password;

 

public String getUsername() {

return username;

}

 

public void setUsername(String username) {

this.username = username;

}

 

public String getPassword() {

return password;

}

 

public void setPassword(String password) {

this.password = password;

}

 

@Override

public String toString() {

return "User [username=" + username + ", password=" + password + "]";

}

}

User [username=null, password=null]


3。 Constructor

Constructor表示一个类的构造器。即构造器的反射对象!

 

3.1 获取Constructor对象

  获取Construcator对象需要使用Class对象,下面API来自Class类:

l Constructor getConstructor(Class… parameterTypes):通过指定的参数类型获取公有构造器反射对象;

l Constructor[] getConstructors():获取所有公有构造器对象;

l Constructor getDeclaredConstructor(Class… parameterTypes):通过指定参数类型获取构造器反射对象。可以是私有构造器对象;

l Constructor[] getDeclaredConstructors():获取所有构造器对象。包含私有构造器;

 

3.2Construcator类常用方法

l String getName():获取构造器名;

l Class getDeclaringClass():获取构造器所属的类型;

l Class[] getParameterTypes():获取构造器的所有参数的类型;

l Class[] getExceptionTypes():获取构造器上声明的所有异常类型;

l T newInstance(Object… initargs):通过构造器反射对象调用构造器。

 

3.3 练习:通过Construcator创建对象

 

User.java

public class User {

private String username;

private String password;

 

public User() {

}

 

public User(String username, String password) {

this.username = username;

this.password = password;

}

 

public String getUsername() {

return username;

}

 

public void setUsername(String username) {

this.username = username;

}

 

public String getPassword() {

return password;

}

 

public void setPassword(String password) {

this.password = password;

}

 

@Override

public String toString() {

return "User [username=" + username + ", password=" + password + "]";

}

}

 

Demo1.java

public class Demo1 {

@Test

public void fun1() throws Exception {

String className = "cn.itcast.User";

Class clazz = Class.forName(className);

Constructor c = clazz.getConstructor(String.class, String.class);

User user = (User)c.newInstance("zhangSan", "123");

System.out.println(user);

}

}

 

4。 Method(类的组成部分)

Class à 类的反射对象

Constructor à 构造器的反射对象

Method表示方法的反射对象

Field à 成员的反射对象

 

4.1 获取Method

获取Method需要通过Class对象,下面是Class类的API

l Method getMethod(String name, Class… parameterTypes):通过方法名和方法参数类型获取方法反射对象,包含父类中声明的公有方法,但不包含所有私有方法;

l Method[] getMethods():获取所有公有方法,包含父类中的公有方法,但不包含任何私有方法;

l Method getDeclaredMethod(String name, Class… parameterTypes):通过方法名和方法参数类型获取本类中声明的方法的反射对象,包含本类中的私有方法,但不包含父类中的任何方法;

l Method[] getDeclaredMethods():获取本类中所有方法,包含本类中的私有方法,但不包含父类中的任何方法。

 

4.2Method常用方法

l String getName():获取方法名;

l Class getDeclaringClass():获取方法所属的类型;

l Class[] getParameterTypes():获取方法的所有参数的类型;

l Class[] getExceptionTypes():获取方法上声明的所有异常类型;

l Class getReturnType():获取方法的返回值类型;

l Object invode(Object obj, Object… args):通过方法反射对象调用方法,如果当前方法是实例方法,那么当前对象就是obj,如果当前方法是static方法,那么可以给obj传递nullargs表示是方法的参数;

 

4.3 练习:通过Method调用方法

  

public class Demo1 {

@Test

public void fun1() throws Exception {

String className = "cn.itcast.User";

Class clazz = Class.forName(className);

Constructor c = clazz.getConstructor(String.class, String.class);

User user = (User)c.newInstance("zhangSan", "123");

Method method = clazz.getMethod("toString");

String result = (String)method.invoke(user);

System.out.println(result);

}

}

 

5。 Field

  Field表示类的成员变量,可以是实例变量,也可以是静态变量。

 

5.1 获取Field对象

获取Field对象需要使用Class对象,下面是Class类的API

l Field getField(String name):通过名字获取公有成员变量的反射对象,包含父类中声明的公有成员变量;

l Field[] getFields():获取所有公有成员变量反射对象,包含父类中声明的公有成员变量;

l Field getDeclaredField(String name):通过名字获取本类中某个成员变量,包含本类的private成员变量,但父类中声明的任何成员变量都不包含;

l Field[] getDeclaredFields():获取本类中声明的所有成员变量,包含private成员变量,但不包含父类中声明的任何成员变量;

 

5.2Field类的常用方法

l String getName():获取成员变量名;

l Class getDeclaringClass():获取成员变量的类型;

l Class getType():获取当前成员变量的类型;

l Object get(Object obj):获取obj对象的成员变量的值;

l void set(Object obj, Object value):设置obj对象的成员变量值为value

 

5.3 练习:通过Field读写成员

User.java

public class User {

public String username;

public String password;

 

public User() {

}

 

public User(String username, String password) {

this.username = username;

this.password = password;

}

 

public String getUsername() {

return username;

}

 

public void setUsername(String username) {

this.username = username;

}

 

public String getPassword() {

return password;

}

 

public void setPassword(String password) {

this.password = password;

}

 

@Override

public String toString() {

return "User [username=" + username + ", password=" + password + "]";

}

}

 

 

Demo1.java

public class Demo1 {

@Test

public void fun1() throws Exception {

String className = "cn.itcast.User";

Class clazz = Class.forName(className);

User user = new User("zhangSan", "123");

Field field1 = clazz.getField("username");

Field field2 = clazz.getField("password");

String username = (String)field1.get(user);

String password = (String)field2.get(user);

System.out.println(username + ", " + password);

field1.set(user, "liSi");

field2.set(user, "456");

System.out.println(user);

}

}

 

6。 AccessibleObject

AccessibleObject类是ConstructorMethodField三个类的父类。AccessibleObject最为重要的方法如下:

l boolean isAccessible():判断当前成员是否可访问;

l void setAccessible(boolean flag):设置当前成员是否可访问。

 

ConstructorMethodField为私有时,如果我们想反射操作,那么就必须先调用反射对象的setAccessible(true)方法,然后才能操作。

User.java

public class User {

private String username;

private String password;

 

public User() {

}

 

public User(String username, String password) {

this.username = username;

this.password = password;

}

 

public String getUsername() {

return username;

}

 

public void setUsername(String username) {

this.username = username;

}

 

public String getPassword() {

return password;

}

 

public void setPassword(String password) {

this.password = password;

}

 

@Override

public String toString() {

return "User [username=" + username + ", password=" + password + "]";

}

}

 

注意,User类的usernamepassword成员变量为private的,这时再通过Field来反射操作这两个成员变量就必须先通过setAccessible(true)设置后才行。

public class Demo1 {

@Test

public void fun1() throws Exception {

String className = "cn.itcast.User";

Class clazz = Class.forName(className);

User user = new User("zhangSan", "123");

Field field1 = clazz.getDeclaredField("username");

Field field2 = clazz.getDeclaredField("password");

field1.setAccessible(true);

field2.setAccessible(true);

String username = (String)field1.get(user);

String password = (String)field2.get(user);

System.out.println(username + ", " + password);

field1.set(user, "liSi");

field2.set(user, "456");

System.out.println(user);

}

}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值