java中反射詳解及實(shí)際應(yīng)用場景
1、介紹
反射(Reflection)是Java語言的一個(gè)特性,它允許程序在運(yùn)行時(shí)動態(tài)地獲取類的信息并操作類或?qū)ο蟮膶傩?、方法和?gòu)造器。
1.1、舉例
想象你有一個(gè)密封的盒子(類),正常情況下你只能通過盒子上的按鈕(公共方法)來操作它。而反射就像是一把X光掃描儀,可以讓你不用打開盒子就能看到里面的所有結(jié)構(gòu)(私有字段、方法等),甚至可以繞過正常的操作方式直接控制內(nèi)部部件。
什么時(shí)候需要用到反射呢?
舉個(gè)生動例子:
class GameCharacter { private int health = 100; // 血量 private String name; public void attack() { /* 攻擊邏輯 */ } private void cheat() { health = 9999; } // 作弊方法 }
沒有反射時(shí):
你只能調(diào)用 attack()方法
無法修改血量health
無法調(diào)用 cheat()方法
使用反射后:
// 獲取角色類的X光照片 Class<?> clazz = GameCharacter.class; // 找到血量字段并修改(無視private) Field healthField = clazz.getDeclaredField("health"); healthField.setAccessible(true); // 萬能鑰匙開鎖 healthField.set(character, 9999); // 修改血量 // 找到作弊方法并調(diào)用 Method cheatMethod = clazz.getDeclaredMethod("cheat"); cheatMethod.setAccessible(true); cheatMethod.invoke(character); // 執(zhí)行作弊
這就好比在游戲運(yùn)行時(shí)突然獲得了修改角色屬性的能力!
1.2、作用
2、核心類
Java反射主要涉及以下幾個(gè)核心類:
Class:表示類的元數(shù)據(jù)
Field:表示類的字段
Method:表示類的方法
Constructor:表示類的構(gòu)造器
3、應(yīng)用場景
3.1、基本反射操作
import java.lang.reflect.*; public class ReflectionDemo { public static void main(String[] args) throws Exception { // 獲取Class對象的三種方式 Class<?> clazz1 = Class.forName("java.lang.String"); Class<?> clazz2 = String.class; Class<?> clazz3 = "hello".getClass(); System.out.println("類名: " + clazz1.getName()); System.out.println("簡單類名: " + clazz1.getSimpleName()); // 獲取所有公共方法 System.out.println("\n公共方法:"); Method[] methods = clazz1.getMethods(); for (Method method : methods) { System.out.println(method.getName()); } // 獲取所有聲明的字段(包括私有) System.out.println("\n所有字段:"); Field[] fields = clazz1.getDeclaredFields(); for (Field field : fields) { System.out.println(field.getName()); } // 創(chuàng)建實(shí)例并調(diào)用方法 String str = (String) clazz1.getConstructor(String.class).newInstance("Hello Reflection"); Method lengthMethod = clazz1.getMethod("length"); int length = (int) lengthMethod.invoke(str); System.out.println("\n字符串長度: " + length); } }
3.2、動態(tài)加載類
// 根據(jù)配置文件動態(tài)加載類 public class PluginManager { public void loadPlugin(String className) throws Exception { Class<?> pluginClass = Class.forName(className); Object plugin = pluginClass.newInstance(); if (plugin instanceof Runnable) { ((Runnable) plugin).run(); } } } // 使用 PluginManager manager = new PluginManager(); manager.loadPlugin("com.example.MyPlugin"); // 類名可以從配置文件中讀取
3.3、調(diào)用私有方法(測試時(shí)常用)
public class SecretClass { private String secretMethod(String input) { return "Secret: " + input; } } // 測試類中使用反射調(diào)用私有方法 public class SecretTest { public static void main(String[] args) throws Exception { SecretClass instance = new SecretClass(); Class<?> clazz = instance.getClass(); Method secretMethod = clazz.getDeclaredMethod("secretMethod", String.class); secretMethod.setAccessible(true); // 突破私有限制 String result = (String) secretMethod.invoke(instance, "Hello"); System.out.println(result); // 輸出: Secret: Hello } }
3.4、JSON/XML序列化與反序列化
3.4.1.json序列化
// 簡單的JSON序列化工具(簡化版) public class JsonSerializer { public static String toJson(Object obj) throws Exception { Class<?> clazz = obj.getClass(); Field[] fields = clazz.getDeclaredFields(); StringBuilder json = new StringBuilder("{"); for (Field field : fields) { field.setAccessible(true); json.append("\"").append(field.getName()).append("\":") .append("\"").append(field.get(obj)).append("\","); } json.deleteCharAt(json.length() - 1).append("}"); return json.toString(); } } // 使用 class Person { private String name = "Alice"; private int age = 25; } Person person = new Person(); System.out.println(JsonSerializer.toJson(person)); // 輸出: {"name":"Alice","age":25}
3.4.2.xml實(shí)現(xiàn)
import java.lang.reflect.*; import java.util.*; public class XmlSerializer { public static String toXml(Object obj) throws Exception { if (obj == null) return "<null/>"; Class<?> clazz = obj.getClass(); StringBuilder xml = new StringBuilder(); // 處理基本類型 if (obj instanceof Number || obj instanceof Boolean || obj instanceof String) { return "<value>" + obj.toString() + "</value>"; } // 處理數(shù)組 if (clazz.isArray()) { xml.append("<array type=\"").append(clazz.getComponentType().getSimpleName()).append("\">"); int length = Array.getLength(obj); for (int i = 0; i < length; i++) { xml.append(toXml(Array.get(obj, i))); } xml.append("</array>"); return xml.toString(); } // 處理集合 if (obj instanceof Collection) { Collection<?> collection = (Collection<?>) obj; xml.append("<collection>"); for (Object item : collection) { xml.append(toXml(item)); } xml.append("</collection>"); return xml.toString(); } // 處理普通對象 xml.append("<").append(clazz.getSimpleName()).append(">"); for (Field field : clazz.getDeclaredFields()) { if (Modifier.isTransient(field.getModifiers())) continue; field.setAccessible(true); Object value = field.get(obj); xml.append("<").append(field.getName()).append(">") .append(toXml(value)) .append("</").append(field.getName()).append(">"); } xml.append("</").append(clazz.getSimpleName()).append(">"); return xml.toString(); } public static void main(String[] args) throws Exception { class Product { private String id = "P1001"; private String name = "Laptop";
輸出:
<Product><id>P1001</id><name>Laptop</name><price>999.99</price><tags><array type="String"><value>electronics</value><value>computer</value></array></tags></Product>
3.5、反射實(shí)現(xiàn)依賴注入
依賴注入是框架(如Spring)中廣泛使用的設(shè)計(jì)模式,它通過反射機(jī)制動態(tài)地將依賴對象注入到目標(biāo)對象中。
1. 簡單依賴注入實(shí)現(xiàn)
import java.lang.reflect.Field; import java.util.HashMap; import java.util.Map; // 模擬一個(gè)簡單的IoC容器 public class SimpleContainer { private Map<String, Object> beans = new HashMap<>(); // 注冊Bean public void registerBean(String name, Object bean) { beans.put(name, bean); } // 依賴注入 public void injectDependencies() throws Exception { for (Object bean : beans.values()) { // 獲取Bean的所有字段 Field[] fields = bean.getClass().getDeclaredFields(); for (Field field : fields) { // 檢查是否有@Autowired注解(這里簡化處理) if (field.getAnnotation(Autowired.class) != null) { // 獲取字段類型 Class<?> fieldType = field.getType(); // 查找匹配的依賴Bean Object dependency = findDependency(fieldType); if (dependency != null) { // 突破私有訪問限制 field.setAccessible(true); // 注入依賴 field.set(bean, dependency); } } } } } // 查找匹配的依賴 private Object findDependency(Class<?> type) { for (Object bean : beans.values()) { if (type.isAssignableFrom(bean.getClass())) { return bean; } } return null; } } // 自定義Autowired注解 @interface Autowired {} // 使用示例 class ServiceA {} class ServiceB { @Autowired private ServiceA serviceA; // 將被自動注入 public void showDependency() { System.out.println("ServiceB中的ServiceA依賴: " + serviceA); } } public class DITest { public static void main(String[] args) throws Exception { SimpleContainer container = new SimpleContainer(); container.registerBean("serviceA", new ServiceA()); container.registerBean("serviceB", new ServiceB()); container.injectDependencies(); ServiceB serviceB = (ServiceB) container.getBean("serviceB"); serviceB.showDependency(); } }
2. 依賴注入原理
Spring框架的依賴注入核心流程:
掃描類路徑,通過反射獲取類的元信息
解析@Component、@Service等注解
解析構(gòu)造器或字段上的@Autowired注解
通過反射創(chuàng)建Bean實(shí)例
通過反射將依賴注入到目標(biāo)字段或構(gòu)造器中
3.6、反射實(shí)現(xiàn)動態(tài)代理
動態(tài)代理是AOP(面向切面編程)的基礎(chǔ),它允許在運(yùn)行時(shí)動態(tài)創(chuàng)建代理對象。
1. JDK動態(tài)代理示例
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; // 業(yè)務(wù)接口 interface UserService { void addUser(String name); void deleteUser(String name); } // 實(shí)際業(yè)務(wù)實(shí)現(xiàn) class UserServiceImpl implements UserService { public void addUser(String name) { System.out.println("添加用戶: " + name); } public void deleteUser(String name) { System.out.println("刪除用戶: " + name); } } // 代理處理器 class LoggingHandler implements InvocationHandler { private Object target; // 被代理對象 public LoggingHandler(Object target) { this.target = target; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // 前置增強(qiáng) System.out.println("準(zhǔn)備執(zhí)行: " + method.getName()); // 反射調(diào)用原始方法 Object result = method.invoke(target, args); // 后置增強(qiáng) System.out.println("執(zhí)行完成: " + method.getName()); return result; } } public class DynamicProxyDemo { public static void main(String[] args) { UserService realService = new UserServiceImpl(); // 創(chuàng)建代理對象 UserService proxyService = (UserService) Proxy.newProxyInstance( UserService.class.getClassLoader(), new Class[]{UserService.class}, new LoggingHandler(realService) ); // 通過代理調(diào)用方法 proxyService.addUser("張三"); proxyService.deleteUser("李四"); } } 輸出: 準(zhǔn)備執(zhí)行: addUser 添加用戶: 張三 執(zhí)行完成: addUser 準(zhǔn)備執(zhí)行: deleteUser 刪除用戶: 李四 執(zhí)行完成: deleteUser
2. CGLIB動態(tài)代理示例
當(dāng)目標(biāo)類沒有實(shí)現(xiàn)接口時(shí),可以使用CGLIB庫:
import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; class ProductService { public void saveProduct(String name) { System.out.println("保存產(chǎn)品: " + name); } } class ProductMethodInterceptor implements MethodInterceptor { public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { System.out.println("CGLIB代理前置處理"); Object result = proxy.invokeSuper(obj, args); System.out.println("CGLIB代理后置處理"); return result; } } public class CglibProxyDemo { public static void main(String[] args) { Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(ProductService.class); enhancer.setCallback(new ProductMethodInterceptor()); ProductService proxy = (ProductService) enhancer.create(); proxy.saveProduct("筆記本電腦"); } } 輸出: CGLIB代理前置處理 保存產(chǎn)品: 筆記本電腦 CGLIB代理后置處理
3.7、反射實(shí)現(xiàn)注解處理
Java反射API提供了以下關(guān)鍵方法來處理注解:
getAnnotation(Class<T>) - 獲取指定類型的注解
getAnnotations
()
- 獲取所有注解isAnnotationPresent(Class<?>) - 檢查是否存在指定注解
1. 定義自定義注解
import java.lang.annotation.*; // 表注解 @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) @interface Table { String name(); } // 列注解 @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) @interface Column { String name(); String type(); }
2. 使用反射處理注解
代碼示例如下:
import java.lang.reflect.Field; // 應(yīng)用注解的實(shí)體類 @Table(name = "user_table") class User { @Column(name = "user_id", type = "bigint") private Long id; @Column(name = "user_name", type = "varchar(50)") private String name; @Column(name = "user_age", type = "int") private Integer age; // 非持久化字段(無Column注解) private transient String temp; } public class AnnotationProcessor { public static void main(String[] args) { // 獲取類注解 Class<User> userClass = User.class; Table tableAnnotation = userClass.getAnnotation(Table.class); if (tableAnnotation != null) { System.out.println("表名: " + tableAnnotation.name()); // 生成建表SQL StringBuilder sql = new StringBuilder(); sql.append("CREATE TABLE ").append(tableAnnotation.name()).append("(\n"); // 處理字段注解 Field[] fields = userClass.getDeclaredFields(); for (Field field : fields) { Column columnAnnotation = field.getAnnotation(Column.class); if (columnAnnotation != null) { sql.append(" ").append(columnAnnotation.name()) .append(" ").append(columnAnnotation.type()) .append(",\n"); } } sql.delete(sql.length()-2, sql.length()); // 刪除最后的逗號和換行 sql.append("\n);"); System.out.println("生成的SQL:\n" + sql); } } } 輸出: 表名: user_table 生成的SQL: CREATE TABLE user_table( user_id bigint, user_name varchar(50), user_age int );
3. 進(jìn)階注解處理
1. 方法級注解與處理
import java.lang.annotation.*; import java.lang.reflect.Method; // 定義權(quán)限注解 @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) @interface Permission { String[] roles() default {}; } // 服務(wù)類 class AdminService { @Permission(roles = {"admin", "superadmin"}) public void deleteUser(String username) { System.out.println("刪除用戶: " + username); } @Permission(roles = {"user", "admin"}) public void viewProfile(String username) { System.out.println("查看用戶資料: " + username); } public void publicMethod() { System.out.println("公開方法,無需權(quán)限"); } } public class PermissionProcessor { public static void main(String[] args) throws Exception { // 模擬當(dāng)前用戶角色 String currentRole = "user"; AdminService service = new AdminService(); Method[] methods = service.getClass().getMethods(); for (Method method : methods) { if (method.isAnnotationPresent(Permission.class)) { Permission permission = method.getAnnotation(Permission.class); boolean hasPermission = false; // 檢查用戶是否有權(quán)限 for (String role : permission.roles()) { if (role.equals(currentRole)) { hasPermission = true; break; } } if (hasPermission) { System.out.println("允許執(zhí)行: " + method.getName()); method.invoke(service, "testUser"); } else { System.out.println("拒絕訪問: " + method.getName() + ",需要角色: " + String.join(",", permission.roles())); } } else { // 沒有權(quán)限注解的方法可以直接執(zhí)行 System.out.println("執(zhí)行無權(quán)限限制方法: " + method.getName()); method.invoke(service); } } } } 輸出: 允許執(zhí)行: viewProfile 查看用戶資料: testUser 拒絕訪問: deleteUser,需要角色: admin,superadmin 執(zhí)行無權(quán)限限制方法: publicMethod 公開方法,無需權(quán)限
2. 參數(shù)級注解與驗(yàn)證
import java.lang.annotation.*; import java.lang.reflect.*; import java.util.*; // 參數(shù)驗(yàn)證注解 @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.PARAMETER) @interface Validate { int min() default 0; int max() default Integer.MAX_VALUE; String pattern() default ""; } class UserService { public void createUser( @Validate(min = 3, max = 20) String username, @Validate(min = 6, pattern = ".*[0-9].*") String password) { System.out.println("創(chuàng)建用戶: " + username); } } public class ValidationProcessor { public static void invokeWithValidation(Object target, Method method, Object... args) throws Exception { Parameter[] parameters = method.getParameters(); for (int i = 0; i < parameters.length; i++) { Validate validate = parameters[i].getAnnotation(Validate.class); if (validate != null) { Object arg = args[i]; if (arg instanceof String) { String value = (String) arg; // 檢查長度 if (value.length() < validate.min()) { throw new IllegalArgumentException( parameters[i].getName() + " 長度不能小于 " + validate.min()); } if (value.length() > validate.max()) { throw new IllegalArgumentException( parameters[i].getName() + " 長度不能大于 " + validate.max()); } // 檢查正則表達(dá)式 if (!validate.pattern().isEmpty() && !value.matches(validate.pattern())) { throw new IllegalArgumentException( parameters[i].getName() + " 不符合格式要求"); } } } } // 所有驗(yàn)證通過,調(diào)用方法 method.invoke(target, args); } public static void main(String[] args) throws Exception { UserService service = new UserService(); Method method = service.getClass().getMethod("createUser", String.class, String.class); // 測試用例 try { invokeWithValidation(service, method, "ab", "123456"); // 用戶名太短 } catch (IllegalArgumentException e) { System.out.println("驗(yàn)證失敗: " + e.getMessage()); } try { invokeWithValidation(service, method, "validUser", "simple"); // 密碼不符合格式 } catch (IllegalArgumentException e) { System.out.println("驗(yàn)證失敗: " + e.getMessage()); } // 成功案例 invokeWithValidation(service, method, "validUser", "pass123"); } } 輸出結(jié)果: 驗(yàn)證失敗: username 長度不能小于 3 驗(yàn)證失敗: password 不符合格式要求 創(chuàng)建用戶: validUser
3. 模擬Spring MVC的控制器處理
import java.lang.annotation.*; import java.lang.reflect.*; import java.util.*; // 模擬Spring MVC注解 @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) @Controller @interface Controller { String value() default ""; } @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) @RequestMapping @interface RequestMapping { String path(); String method() default "GET"; } // 控制器類 @Controller("/user") class UserController { @RequestMapping(path = "/list", method = "GET") public List<String> listUsers() { return Arrays.asList("Alice", "Bob", "Charlie"); } @RequestMapping(path = "/add", method = "POST") public String addUser(String username) { return "添加用戶成功: " + username; } } public class MvcSimulator { private Map<String, Method> routeMap = new HashMap<>(); public void init() { // 掃描所有Controller類 Class<?>[] controllers = {UserController.class}; // 實(shí)際框架會掃描包 for (Class<?> controller : controllers) { Controller controllerAnnotation = controller.getAnnotation(Controller.class); String basePath = controllerAnnotation.value(); // 處理每個(gè)方法 for (Method method : controller.getDeclaredMethods()) { if (method.isAnnotationPresent(RequestMapping.class)) { RequestMapping mapping = method.getAnnotation(RequestMapping.class); String fullPath = basePath + mapping.path(); routeMap.put(mapping.method() + ":" + fullPath, method); } } } } public Object handleRequest(String httpMethod, String path, Object... args) throws Exception { String key = httpMethod + ":" + path; Method method = routeMap.get(key); if (method != null) { // 實(shí)際框架會處理參數(shù)綁定等復(fù)雜邏輯 return method.invoke(method.getDeclaringClass().newInstance(), args); } throw new RuntimeException("404 Not Found"); } public static void main(String[] args) throws Exception { MvcSimulator simulator = new MvcSimulator(); simulator.init(); // 模擬HTTP請求 Object result1 = simulator.handleRequest("GET", "/user/list"); System.out.println("GET /user/list => " + result1); Object result2 = simulator.handleRequest("POST", "/user/add", "David"); System.out.println("POST /user/add => " + result2); try { simulator.handleRequest("GET", "/not/exist"); } catch (Exception e) { System.out.println("GET /not/exist => " + e.getMessage()); } } } 輸出: GET /user/list => [Alice, Bob, Charlie] POST /user/add => 添加用戶成功: David GET /not/exist => 404 Not Found
3.8、代碼提示、idea自動補(bǔ)全
IDE功能:如代碼提示、自動補(bǔ)全等功能利用反射獲取類信息
實(shí)現(xiàn)代碼提示和自動補(bǔ)全主要需要以下反射操作:
獲取類的所有公共方法(getMethods())
獲取類的所有聲明方法(getDeclaredMethods())
獲取方法的參數(shù)信息(getParameterTypes())
獲取類的字段信息(getFields(), getDeclaredFields())
獲取類的構(gòu)造函數(shù)(getConstructors())
1. 類成員自動補(bǔ)全
import java.lang.reflect.*; import java.util.*; public class CodeCompletion { private static final Set<String> JAVA_KEYWORDS = new HashSet<>(Arrays.asList( "public", "private", "protected", "static", "void", "class", "interface" )); public static List<String> getClassSuggestions(Class<?> clazz, String prefix) { List<String> suggestions = new ArrayList<>(); // 獲取公共方法 for (Method method : clazz.getMethods()) { if (method.getName().startsWith(prefix) { suggestions.add(method.getName() + "()"); } } // 獲取公共字段 for (Field field : clazz.getFields()) { if (field.getName().startsWith(prefix)) { suggestions.add(field.getName()); } } return suggestions; } public static List<String> getContextAwareSuggestions(Class<?> clazz, String context, String prefix) { List<String> suggestions = new ArrayList<>(); if (context.endsWith(".")) { // 對象成員提示 try { Field field = clazz.getField(context.substring(0, context.length()-1)); return getClassSuggestions(field.getType(), prefix); } catch (Exception e) { // 處理異常 } } else if (JAVA_KEYWORDS.contains(context)) { // 關(guān)鍵字后不提示 return suggestions; } else { // 類靜態(tài)成員提示 return getClassSuggestions(clazz, prefix); } return suggestions; } public static void main(String[] args) { Class<?> stringClass = String.class; System.out.println("String類以'comp'開頭的方法/字段:"); System.out.println(getClassSuggestions(stringClass, "comp")); System.out.println("\nString類以'to'開頭的方法/字段:"); System.out.println(getClassSuggestions(stringClass, "to")); } } 輸出: String類以'comp'開頭的方法/字段: [compareTo(), compareToIgnoreCase()] String類以'to'開頭的方法/字段: [toCharArray(), toLowerCase(), toLowerCase(), toUpperCase(), toUpperCase(), toString(), toLowerCase(), toUpperCase()]
2. 方法參數(shù)提示
import java.lang.reflect.*; import java.util.*; public class MethodParameterHint { public static Map<String, List<String>> getMethodParameterHints(Class<?> clazz) { Map<String, List<String>> hints = new HashMap<>(); for (Method method : clazz.getMethods()) { List<String> params = new ArrayList<>(); for (Parameter param : method.getParameters()) { params.add(param.getType().getSimpleName() + " " + param.getName()); } String methodKey = method.getName() + "(" + String.join(", ", params) + ")"; hints.put(methodKey, params); } return hints; } public static void printMethodHints(Class<?> clazz, String methodPrefix) { System.out.println("方法名以'" + methodPrefix + "'開頭的方法簽名:"); for (Method method : clazz.getMethods()) { if (method.getName().startsWith(methodPrefix)) { System.out.print(method.getName() + "("); Parameter[] params = method.getParameters(); for (int i = 0; i < params.length; i++) { if (i > 0) System.out.print(", "); System.out.print(params[i].getType().getSimpleName() + " " + params[i].getName()); } System.out.println(")"); } } } public static void main(String[] args) { Class<?> listClass = List.class; System.out.println("List接口所有方法參數(shù)提示:"); Map<String, List<String>> hints = getMethodParameterHints(listClass); hints.forEach((k, v) -> System.out.println(k)); System.out.println("\n---\n"); printMethodHints(listClass, "add"); } } 輸出: List接口所有方法參數(shù)提示: add(E e) addAll(Collection<? extends E> c) ... add(int index, E element) 方法名以'add'開頭的方法簽名: add(E e) add(int index, E element) addAll(Collection<? extends E> c) addAll(int index, Collection<? extends E> c)
4、反射的優(yōu)缺點(diǎn)
優(yōu)點(diǎn):
極大的靈活性,可以在運(yùn)行時(shí)動態(tài)操作
可以訪問類的私有成員(突破封裝)
適合開發(fā)通用框架和工具
缺點(diǎn):
性能開銷較大(比直接調(diào)用慢)
破壞封裝性,可能帶來安全問題
代碼可讀性降低,調(diào)試?yán)щy
5、總結(jié)
記?。?strong>反射是Java的"元"能力,強(qiáng)大但應(yīng)慎用,就像超能力不能隨便在公共場合使用一樣!
到此這篇關(guān)于java中反射詳解及實(shí)際應(yīng)用場景的文章就介紹到這了,更多相關(guān)java反射詳解內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Springboot如何切換默認(rèn)的Tomcat容器
這篇文章主要介紹了Springboot如何切換默認(rèn)的Tomcat容器,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-06-06Java中volatile關(guān)鍵字的作用是什么舉例詳解
這篇文章主要介紹了Java中volatile關(guān)鍵字的作用是什么的相關(guān)資料,volatile關(guān)鍵字在Java中用于修飾變量,提供可見性和禁止指令重排的特性,但不保證原子性,它通過內(nèi)存屏障實(shí)現(xiàn)這些特性,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下2025-04-04詳解Java如何通過裝飾器模式擴(kuò)展系統(tǒng)功能
這篇文章主要為大家詳細(xì)介紹了Java如何通過裝飾器模式擴(kuò)展系統(tǒng)功能,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2023-04-04Java項(xiàng)目中實(shí)現(xiàn)使用traceId跟蹤請求全流程日志
這篇文章主要介紹了Java項(xiàng)目中實(shí)現(xiàn)使用traceId跟蹤請求全流程日志方式,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-08-08Java實(shí)現(xiàn)鼠標(biāo)拖拽移動界面組件
在Java中,F(xiàn)rame或者JFrame自身已經(jīng)實(shí)現(xiàn)了鼠標(biāo)拖拽標(biāo)題欄移動窗口的功能。但是Jframe的樣式實(shí)在無法令人滿意,那你又該怎么實(shí)現(xiàn)鼠標(biāo)拖拽移動窗口的目的呢?今天我們來探討下2014-09-09全鏈路監(jiān)控平臺Pinpoint?SkyWalking?Zipkin選型對比
這篇文章主要為大家介紹了全鏈路監(jiān)控平臺Pinpoint?SkyWalking?Zipkin實(shí)現(xiàn)的選型對比,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步2022-03-03JavaWeb dbutils執(zhí)行sql命令并遍歷結(jié)果集時(shí)不能查到內(nèi)容的原因分析
這篇文章主要介紹了JavaWeb dbutils執(zhí)行sql命令并遍歷結(jié)果集時(shí)不能查到內(nèi)容的原因分析及簡單處理方法,文中給大家介紹了javaweb中dbutils的使用,需要的朋友可以參考下2017-12-12Java中基于DeferredResult的異步服務(wù)詳解
這篇文章主要介紹了Java中基于DeferredResult的異步服務(wù)詳解,DeferredResult字面意思是"延遲結(jié)果",它允許Spring MVC收到請求后,立即釋放(歸還)容器線程,以便容器可以接收更多的外部請求,提升吞吐量,需要的朋友可以參考下2023-12-12