IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> JAVA-反射机制详解 -> 正文阅读

[Java知识库]JAVA-反射机制详解

1 反射的概念

(1)JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
(2)要想解剖一个类,必须先要获取到该类的字节码文件对象。而解剖使用的就是Class类中的方法.所以先要获取到每一个字节码文件对应的Class类型的对象。
(3)Java属于先编译再运行的语言,程序中对象的类型在编译期就确定下来了,而当程序在运行时可能需要动态加载某些类,这些类因为之前用不到,所以没有被加载到JVM。通过反射,可以在运行时动态地创建对象并调用其属性,不需要提前在编译期知道运行的对象是谁。

2 反射的原理

下图是类的正常加载过程、反射原理与class对象:
Class对象的由来是将.class文件读入内存,并为之创建一个Class对象。
image.png

3 反射的优缺点:

1、优点:在运行时获得类的各种内容,进行反编译,对于Java这种先编译再运行的语言,能够让我们很方便的创建灵活的代码,这些代码可以在运行时装配,无需在组件之间进行源代码的链接,更加容易实现面向对象。
?

2、缺点:
(1)反射会消耗一定的系统资源,因此,如果不需要动态地创建一个对象,那么就不需要用反射;
(2)反射调用方法时可以忽略权限检查,因此可能会破坏封装性而导致安全问题。

4 反射的用途:

1、反编译:.class–>.java
?

2、通过反射机制访问java对象的属性方法构造方法
?

3、当我们在使用IDE,比如Ecplise时,当我们输入一个对象或者类,并想调用他的属性和方法是,一按点号,编译器就会自动列出他的属性或者方法,这里就是用到反射。
?

4、反射最重要的用途就是开发各种通用框架。比如很多框架(Spring)都是配置化的(比如通过XML文件配置Bean),为了保证框架的通用性,他们可能需要根据配置文件加载不同的类或者对象,调用不同的方法,这个时候就必须使用到反射了,运行时动态加载需要的加载的对象。

5 反射的使用

5.1 获取Class对象的三种方式

(1)Object–>getClass()
(2)任何数据类型(包括基本的数据类型)都有一个“静态”的class属性
(3)通过Class类的静态方法:forName(String className)(最常用

5.1.1 Object.getClass()

Object类中的getClass方法、因为所有类都继承Object类。从而调用Object类来获取。

5.1.2 获取Class对象的三种方式代码实现

package com.pikaqiu.fs;

import com.pikaqiu.entity.User;

public class FanShe {
	public static void main(String[] args) {
		// 第一种:Object.getClass();
		User user = new User();
		Class userClass1 = user.getClass();
		System.out.println(userClass1);

		// 第二种: java中每个类型都有class 属性
		Class userClass2 = User.class;
		System.out.println(userClass2);
		System.out.println(userClass1 == userClass2);

		// 第三种:Class.forName(String className)
		try {
			Class userClass3 = Class.forName("com.pikaqiu.entity.User");
			System.out.println(userClass3);
			System.out.println(userClass1 == userClass3);
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
	}
}

注意:在运行期间,一个类,只有一个Class对象产生

三种方式常用第三种,第一种对象都有了还要反射干什么。第二种需要导入类的包,依赖太强,不导包就抛编译错误。一般都第三种,一个字符串可以传入也可写在配置文件中等多种方法。

5.2 通过反射获取构造方法

5.2.1 批量的方法

  1. public Constructor[] getConstructors():所有"公有的"构造方法
  2. public Constructor[] getDeclaredConstructors():获取所有的构造方法(包括私有、受保护、默认、公有)

5.2.2 获取单个的方法,并调用

  1. public Constructor getConstructor(Class… parameterTypes):获取单个的"公有的"构造方法:
  2. public Constructor getDeclaredConstructor(Class… parameterTypes):获取"某个构造方法"可以是私有的,或受保护、默认、公有;

5.2.3 调用构造方法

Constructor–>newInstance(Object… initargs)

5.2.4 代码实现

User类:

package com.pikaqiu.entity;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;

import javax.naming.Name;

@Component(value = "user")
public class User {
    public String name;
    public int age;

    //(默认的构造方法)
    User(String name){
        System.out.println("(默认)的构造方法 s = " + name);
    }

    //无参构造方法
    public User(){
        System.out.println("调用了公有、无参构造方法执行了。。。");
    }

    //有一个参数的构造方法
    public User(char name){
        System.out.println("姓名:" + name);
    }

    //有多个参数的构造方法
    public User(String name ,int age){
        System.out.println("姓名:"+name+"年龄:"+ age);//这的执行效率有问题,以后解决。
    }

    //受保护的构造方法
    protected User(boolean n){
        System.out.println("受保护的构造方法 n = " + n);
    }

    //私有构造方法
    private User(int age){
        System.out.println("私有的构造方法   年龄:"+ age);
    }

}

构造函数调用:

package com.pikaqiu.fs;

import jdk.nashorn.internal.runtime.logging.DebugLogger;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.net.SocketTimeoutException;
import java.util.zip.CheckedOutputStream;

public class GetConstructor {
	public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
		// 1. 加载Class对象
		Class name = Class.forName("com.pikaqiu.entity.User"); // 包名.类名

		// 2. 获取所有共有构造函数
		System.out.println("**********************所有公有构造方法*********************************");
		Constructor[] constructors = name.getConstructors();
		for (Constructor constructor : constructors) {
			System.out.println(constructor);
		}


		// 2. 获取所有的构造方法(包括:私有、受保护、默认、公有)
		System.out.println("************所有的构造方法(包括:私有、受保护、默认、公有)***************");
		Constructor[] declaredConstructors = name.getDeclaredConstructors();
		for (Constructor declaredConstructor : declaredConstructors) {
			System.out.println(declaredConstructor);
		}

		// 3. 获取单个公有、无参的构造方法
		System.out.println("*****************获取公有、无参的构造方法*******************************");
		Constructor constructor = name.getConstructor(null);
		System.out.println(constructor);
		//1>、因为是无参的构造方法所以类型是一个null,不写也可以:这里需要的是一个参数的类型,切记是类型
		//2>、返回的是描述这个无参构造函数的类对象。

		// 4. 获取私有构造方法,并调用
		System.out.println("******************获取私有构造方法,并调用*******************************");
		Constructor declaredConstructor = name.getDeclaredConstructor(int.class);
		System.out.println(declaredConstructor);
		// 暴力反射
		declaredConstructor.setAccessible(true); // 取消java语言访问检查
		Object o = declaredConstructor.newInstance(33);
		System.out.println(o);

	}
}

运行结果:

**********************所有公有构造方法*********************************
public com.pikaqiu.entity.User(java.lang.String,int)
public com.pikaqiu.entity.User()
public com.pikaqiu.entity.User(char)
************所有的构造方法(包括:私有、受保护、默认、公有)***************
private com.pikaqiu.entity.User(int)
protected com.pikaqiu.entity.User(boolean)
public com.pikaqiu.entity.User(java.lang.String,int)
com.pikaqiu.entity.User(java.lang.String)
public com.pikaqiu.entity.User()
public com.pikaqiu.entity.User(char)
*****************获取公有、无参的构造方法*******************************
public com.pikaqiu.entity.User()
******************获取私有构造方法,并调用*******************************
private com.pikaqiu.entity.User(int)
私有的构造方法   年龄:33
com.pikaqiu.entity.User@5e481248

5.3 获取成员变量并调用

5.3.1 批量的方法

  1. Field[] getFields():获取所有的"公有字段"
  2. Field[] getDeclaredFields():获取所有字段,包括:私有、受保护、默认、公有;

5.3.2 获取单个的方法

  1. public Field getField(String fieldName):获取某个"公有的"字段;
  2. public Field getDeclaredField(String fieldName):获取某个字段(可以是私有的)

5.3.3 设置字段的值

Field --> public void set(Object obj,Object value):

  • 参数说明:
    • obj:要设置的字段所在的对象;
    • value:要为字段设置的值;

5.3.4 代码实现

User类

package com.pikaqiu.entity;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;

import javax.naming.Name;

@Component(value = "user")
public class User {
    public String name;
    protected int age;
    char sex;
    private String phone;

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", sex=" + sex +
                ", phone='" + phone + '\'' +
                '}';
    }
}

成员变量调用

package com.pikaqiu.fs;

import com.pikaqiu.entity.User;
import jdk.nashorn.internal.runtime.Source;
import jdk.nashorn.internal.runtime.logging.DebugLogger;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.net.SocketTimeoutException;
import java.util.zip.CheckedOutputStream;


public class GetConstructor {
	public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchFieldException {
		// 1. 加载Class对象
		Class name = Class.forName("com.pikaqiu.entity.User"); // 包名.类名

		// 2.获取字段
		System.out.println("************获取所有公有的字段********************");
		Field[] fields = name.getFields();
		for (Field field : fields) {
			System.out.println(field);
		}

		System.out.println("************获取所有的字段(包括私有、受保护、默认的)********************");
		Field[] declaredFields = name.getDeclaredFields();
		for (Field declaredField : declaredFields) {
			System.out.println(declaredField);
		}

		System.out.println("*************获取公有字段**并调用***********************************");
		Field name1 = name.getField("name");
		System.out.println(name1);
		// 获取一个对象
		Object o = name.getConstructor().newInstance(); //产生User对象--》User user = new User();
		// 为字段值赋值
		name1.set(o, "haha");
		User o1 = (User) o;
		System.out.println("name:" + o1.name);

		System.out.println("**************获取私有字段****并调用********************************");
		Field phone = name.getDeclaredField("phone");
		System.out.println(phone);
		phone.setAccessible(true);
		phone.set(o,"2341241234");
		System.out.println(o1);
	}
}

结果:

************获取所有公有的字段********************
public java.lang.String com.pikaqiu.entity.User.name
************获取所有的字段(包括私有、受保护、默认的)********************
public java.lang.String com.pikaqiu.entity.User.name
protected int com.pikaqiu.entity.User.age
char com.pikaqiu.entity.User.sex
private java.lang.String com.pikaqiu.entity.User.phone
*************获取公有字段**并调用***********************************
public java.lang.String com.pikaqiu.entity.User.name
调用了公有、无参构造方法执行了。。。
name:haha
**************获取私有字段****并调用********************************
private java.lang.String com.pikaqiu.entity.User.phone
User{name='haha', age=0, sex= , phone='2341241234'}

5.4 获取成员方法并调用

5.4.1 批量的方法

  1. public Method[] getMethods():获取所有"公有方法";(包含了父类的方法也包含Object类)
  2. public Method[] getDeclaredMethods():获取所有的成员方法,包括私有的(不包括继承的)

5.4.2 获取单个的:

  1. public Method getMethod(String name,Class<?>… parameterTypes):

    • 参数:
      • name : 方法名;
      • Class … : 形参的Class类型对象
  2. public Method getDeclaredMethod(String name,Class<?>… parameterTypes)

5.4.3 调用方法:

  1. Method --> public Object invoke(Object obj,Object… args):
    参数说明:
    • obj : 要调用方法的对象;
    • args:调用方式时所传递的实参;

5.4.4 代码实现

User类

package com.pikaqiu.entity;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;

import javax.naming.Name;

@Component(value = "user")
public class User {
    // 成员方法
    public void show1(String s){
        System.out.println("调用了:公有的,String参数的show1(): s = " + s);
    }
    protected void show2(){
        System.out.println("调用了:受保护的,无参的show2()");
    }
    void show3(){
        System.out.println("调用了:默认的,无参的show3()");
    }
    private String show4(int age){
        System.out.println("调用了,私有的,并且有返回值的,int参数的show4(): age = " + age);
        return "abcd";
    }

}

获取成员方法

package com.pikaqiu.fs;

import com.pikaqiu.entity.User;
import jdk.nashorn.internal.runtime.Source;
import jdk.nashorn.internal.runtime.logging.DebugLogger;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.SocketTimeoutException;
import java.util.zip.CheckedOutputStream;

public class GetConstructor {
	public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchFieldException {
		// 1. 加载Class对象
		Class name = Class.forName("com.pikaqiu.entity.User"); // 包名.类名

		//2.获取所有公有方法
		System.out.println("***************获取所有的”公有“方法*******************");
		name.getMethods();
		Method[] methodArray = name.getMethods();
		for(Method m : methodArray){
			System.out.println(m);
		}
		System.out.println("***************获取所有的方法,包括私有的*******************");
		methodArray = name.getDeclaredMethods();
		for(Method m : methodArray){
			System.out.println(m);
		}
		System.out.println("***************获取公有的show1()方法*******************");
		Method m = name.getMethod("show1", String.class);
		System.out.println(m);
		//实例化一个Student对象
		Object obj = name.getConstructor().newInstance();
		m.invoke(obj, "刘德华");

		System.out.println("***************获取私有的show4()方法******************");
		m = name.getDeclaredMethod("show4", int.class);
		System.out.println(m);
		m.setAccessible(true);//解除私有限定
		Object result = m.invoke(obj, 20);//需要两个参数,一个是要调用的对象(获取有反射),一个是实参
		System.out.println("返回值:" + result);

	}
}

结果

***************获取所有的”公有“方法*******************
public java.lang.String com.pikaqiu.entity.User.toString()
public void com.pikaqiu.entity.User.setName(java.lang.String)
public void com.pikaqiu.entity.User.show1(java.lang.String)
public final void java.lang.Object.wait() throws java.lang.InterruptedException
public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
public boolean java.lang.Object.equals(java.lang.Object)
public native int java.lang.Object.hashCode()
public final native java.lang.Class java.lang.Object.getClass()
public final native void java.lang.Object.notify()
public final native void java.lang.Object.notifyAll()
***************获取所有的方法,包括私有的*******************
public java.lang.String com.pikaqiu.entity.User.toString()
public void com.pikaqiu.entity.User.setName(java.lang.String)
private java.lang.String com.pikaqiu.entity.User.show4(int)
void com.pikaqiu.entity.User.show3()
public void com.pikaqiu.entity.User.show1(java.lang.String)
protected void com.pikaqiu.entity.User.show2()
***************获取公有的show1()方法*******************
public void com.pikaqiu.entity.User.show1(java.lang.String)
调用了公有、无参构造方法执行了。。。
调用了:公有的,String参数的show1(): s = 刘德华
***************获取私有的show4()方法******************
private java.lang.String com.pikaqiu.entity.User.show4(int)
调用了,私有的,并且有返回值的,int参数的show4(): age = 20
返回值:abcd

5.5 反射的应用

5.5.1 泛型擦除

将已存在的ArrayList集合中添加一个字符串数据

package com.pikaqiu.fs;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;

public class FanShenTest {
	public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
		ArrayList<Integer> list = new ArrayList<Integer>();
		// 添加元素到集合
		list.add(1);
		list.add(new Integer("234"));
		list.add(new Integer(5));

		System.out.println(list);

		//通过反射技术,实现添加任意类型的元素
		//1, 获取字节码文件对象
		Class aClass = Class.forName("java.util.ArrayList");
		//2, 找到add()方法
		Method add = aClass.getMethod("add", Object.class);
		//3,  执行add()方法
		add.invoke(list, "haha");
		System.out.println(list);

	}
}

5.5.2 反射配置文件

  1. 通过反射配置文件,运行配置文件中指定类的对应方法

读取properties.txt文件中的数据,通过反射技术,来完成User对象的创建
properties.txt文件内容如下:

className=com.pikaqiu.entity.User
methodName=method
  1. User对象
package com.pikaqiu.entity;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;

import javax.naming.Name;

@Component(value = "user")
public class User {
    public String name;
    public int age;
    private String address;

    public User(String name, int age, String address){
        this.name = name;
        this.age = age;
        this.address = address;
        System.out.println("带有String, int, String的构造方法");
    }

    //私有方法
    private void method(){
        System.out.println("私有方法");
    }

    @Override
    public String toString() {
        return "Person [name=" + name + ", age=" + age + ", address=" + address+ "]";
    }

}

  1. 读取配置文件,调用指定类中的对应方法
package com.pikaqiu.fs;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Properties;

public class FanSheTest2 {
	public static void main(String[] args) throws IOException, ClassNotFoundException, IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchMethodException {
		// 通过Properties集合从文件中读取数据
		Properties properties = new Properties();
		// 读取文件中的数据到集合中
		String name = "F:\\java基础学习\\复习testcode\\SpringReview\\src\\main\\resources\\properties.txt";
		properties.load(new FileInputStream(name));
		// 获取键所对应的值
		String className = properties.getProperty("className");
		System.out.println(className);


		// 1,获取Person.class 字节码文件对象
		Class aClass = Class.forName(className);
		// 2,获取构造方法
		Constructor constructor = aClass.getConstructor(String.class, int.class, String.class);

		// 3. 创建对象
		Object o = constructor.newInstance("小明", 20, "中国");
		System.out.println(o);
		// 4,获取指定的方法
		String methodName = properties.getProperty("methodName");
		Method m5 = aClass.getDeclaredMethod(methodName, null);
		// 5,开启暴力访问
		m5.setAccessible(true);
		// 6,执行找到的方法
		m5.invoke(o, null);


	}
}
  1. 结果
com.pikaqiu.entity.User
带有String, int, String的构造方法
Person [name=小明, age=20, address=中国]
私有方法

6 知识点总结

6.1 如何获取.Class文件对象

  1. 通过Object类 getClass()方法获取 Class对象

  2. 通过类名.class 方式 获取 Class对象

  3. 通过反射的方式, Class.forName(String classname) 获取Class对象

    public static Class<?> forName(String className)throws ClassNotFoundException
    返回与带有给定字符串名的类或接口相关联的Class 对象
    

6.2 通过反射, 获取类中的构造方法,并完成对象的创建

  1. 获取指定的构造方法

     ?public Constructor<T> getConstructor(Class<?>... parameterTypes)
     获取指定的public修饰的构造方法 
    
     public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)
    
     获取指定的构造方法,包含私有的
    
  2. 获取所有的构造方法

     public Constructor<?>[] getConstructors() 获取所有的public 修饰的构造方法
     public Constructor<?>[] getDeclaredConstructors() 获取所有的构造方法,包含私有的
    

?

6.3 通过反射, 获取类中的构造方法,并完成对象的创建

步骤:

  1. 获取字节码文件对象

  2. 通过字节码文件对象 ,获取到指定的构造方法

     getConstructor(参数);
    
  3. 通过构造方法,创建对象

     public T newInstance(Object... initargs)
    

6.4 私有构造方法,创建对象

  1. 获取字节码文件对象

  2. 通过字节码文件对象 ,获取到指定的构造方法

     getDeclaredConstructor (参数);
    
  3. 暴力访问

     con.setAccessible(true);
    
  4. 通过构造方法,创建对象

     public T newInstance(Object... initargs)
    

6.5 通过反射,获取Class文件中的方法

  1. 获取指定的方法

     ?public Method getMethod(String name, Class<?>... parameterTypes)
     获取指定的public方法
     public Method getDeclaredMethod(String name, Class<?>... parameterTypes)
     获取指定的任意方法,包含私有的
    
  2. 获取所有的方法

      public Method[] getMethods() 获取本类与父类中所有public 修饰的方法
      public Method[] getDeclaredMethods()获取本类中所有的方法,包含私有的
    

6.6 通过反射,调用方法

步骤:

  1. 获取Class对象

  2. 获取构造方法,创建对象

  3. 获取指定的public方法

  4. 执行方法

     public Object invoke(Object obj, Object... args)
    

6.6 私有方法的调用:

  1. 获取Class对象

  2. 获取构造方法,创建对象

  3. 获取指定的private方法

  4. 开启暴力访问

     m5.setAccessible(true);
    
  5. 执行方法

     public Object invoke(Object obj, Object... args)
    

6.7 通过反射,获取成员变量(字段)

  1. 获取指定的成员变量

     public Field getField(String name) 获取public修饰的成员变量
     public Field getDeclaredField(String name) 获取任意的成员变量,包含私有
    
  2. 获取所有的成员变量

     public Field[] getFields() 获取所有public修饰的成员变量
     public Field[] getDeclaredFields() 获取司所有的成员变量,包含私有
    

6.8 通过反射,获取成员变量,并赋值使用

步骤:

  1. 获取字节码文件对象

  2. 获取构造方法,创建对象

  3. 获取指定的成员变量

  4. 对成员变量赋值\获取值操作

     public void set(Object obj,  Object value) 赋值
     public Object get(Object obj) 获取值
    

6.9 私有成员变量的使用

步骤:

  1. 获取字节码文件对象

  2. 获取构造方法,创建对象

  3. 获取指定的成员变量

  4. 开启暴力访问

     phone.setAccessible(true);
    
  5. 对成员变量赋值\获取值操作

     public void set(Object obj,  Object value) 赋值
     public Object get(Object obj) 获取值
    

参考文献:

  1. https://blog.csdn.net/a745233700/article/details/82893076
  2. https://blog.csdn.net/sinat_38259539/article/details/71799078?spm=1001.2101.3001.6650.12&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ELandingCtr%7ERate-12.queryctrv4&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7ELandingCtr%7ERate-12.queryctrv4&utm_relevant_index=18
    ?
  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-03-08 22:14:58  更:2022-03-08 22:18:09 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 10:36:23-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码