Java---类反射(2)---类反射加强

谙忆 2021-01-21 15:57:05
java 反射 加强 java---


经过前面的一篇博客,Java—类反射(1),相信大家对类反射有了一定的了解了。 下面来进行对类反射的加强,了解一下怎么通过类反射去new一个对象, 怎么通过类反射去访问其他类的方法。 怎么通过类反射去访问其他类的成员变量。

大家也许认为一个类的私有方法,私有的成员变量是其他类访问不到。但是,类反射是可以通过暴力访问去访问的。

还有:最后要模拟Java内省的功能

类的调用(调用类中的成员)

* 构造类对象

使用构造器新建对象。根据指定的参数类型找到相应的构造函数,传入相应参数调用执行,以创建一个新的对象实例。

代码示例 Person类代码:

package cn.hncu.reflect;
import java.io.IOException;
/**
* @author 陈浩翔
*
* @version 1.0 2016-5-2
*/
public class Person extends Parent {
String name;
private int age;
public int num;
public static String schoolName;
public Person() {
this("naName", 0);
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public Person(int age) throws IOException, NumberFormatException {
this("naName", age);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
protected void setAge(int age) {
this.age = age;
}
private int sum(int a) {
return 0;
}
private int sum() {
return 0;
}
int aa(String a, int b) throws IOException, NumberFormatException {
return 0;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + ", num=" + num + "]";
}
}
class Parent{
public static final int N=100;
}

构造类对象:

package cn.hncu.reflect;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
/**
* 类反射的演示
* @author 陈浩翔
*
* @version 1.0 2016-5-2
*/
public class ReflectOperateObj {
private static final String CLASS_FILE_NAME="cn.hncu.reflect.Person";
public static void main(String[] args) {
try {
operateConstructor(CLASS_FILE_NAME);
} catch (ReflectiveOperationException e) {
e.printStackTrace();
}
}
/**
* 一、演示:使用构造器来新建对象
* @param classFileName
* @throws ReflectiveOperationException
*/
private static void operateConstructor(String classFileName) throws ReflectiveOperationException {
Class cls = Class.forName(CLASS_FILE_NAME);
//1 无参构造方法的使用----简单且以后用得最多的
//Object obj = cls.newInstance();
//2 有参构造方法的使用
//用类反射的方式来执行 Object obj = new Person("Jack",20);
//2.1获取指定"参数列表类型"的构造器---Constructor对象
Class parameterTypes[] = new Class[2];
parameterTypes[0] = String.class;
parameterTypes[1] = int.class;
Constructor con= cls.getConstructor(parameterTypes);//※1※
//2.2调用构造器来new对象
Object initargs[] = new Object[2];
initargs[0] = new String("Jack");
initargs[1] = new Integer(20);
Object resultObj = con.newInstance(initargs);//※2※
System.out.println(resultObj);
}
}

输出结果:

Person [name=Jack, age=20, num=0]

* 调用方法

根据方法名称执行方法。根据方法名与参数类型匹配指定的方法,传入相应参数与对象进行调用执行。若是静态方法,则不需传入具体对象。

代码示例:

Person还是之前的Person类…

演示:调用无参普通方法:

package cn.hncu.reflect;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
/**
* 类反射的演示
* @author 陈浩翔
*
* @version 1.0 2016-5-2
*/
public class ReflectOperateObj {
private static final String CLASS_FILE_NAME="cn.hncu.reflect.Person";
public static void main(String[] args) {
try {
callMethod(CLASS_FILE_NAME);
} catch (ReflectiveOperationException e) {
e.printStackTrace();
}
}
/**
* 二、演示:调用无参普通方法
* @param classFileName
* @throws ReflectiveOperationException
*/
private static void callMethod(String classFileName) throws ReflectiveOperationException{
Class cls = Class.forName(CLASS_FILE_NAME);
//需求:调用空参方法 p.toString()
//1.1必须要用一个类对象
Object obj = cls.newInstance();
//1.2用对象来调方法
//1.2.1先拿到对应方法的Method对象
Method m = cls.getMethod("toString", null);
//1.2.2用obj和method来调用该方法
Object returnValue = m.invoke(obj, null);
System.out.println(returnValue);
}
}

输出结果:

Person [name=naName, age=0, num=0]

演示:调用有参普通方法

Person相比之前,加了一个double sum(int , double)方法。

public double sum( int n, double d){
double sum =0;
for(int i=1;i<=n;i++){
sum +=d;
}
return sum;
}

演示类:

package cn.hncu.reflect;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
/**
* 类反射的演示
* @author 陈浩翔
*
* @version 1.0 2016-5-2
*/
public class ReflectOperateObj {
private static final String CLASS_FILE_NAME="cn.hncu.reflect.Person";
public static void main(String[] args) {
try {
callMethod2(CLASS_FILE_NAME);
} catch (ReflectiveOperationException e) {
e.printStackTrace();
}
}
/**
* 三、演示:调用有参普通方法
* @param classFileName
* @throws ReflectiveOperationException
*/
private static void callMethod2(String classFileName) throws ReflectiveOperationException{
Class cls = Class.forName(CLASS_FILE_NAME);
//需求:调用有参方法 p.sum(10,2.34)
//1.1必须要用一个类对象
Object obj = cls.newInstance();
//**1.2用对象来调方法
//***1.2.1先拿到对应方法的Method对象
Class parameterTypes[] = new Class[2];//形参列表---类型列表---Class数组
//paramTypes[0]=int.class;//OK
parameterTypes[0]=Integer.TYPE;//OK
//paramTypes[0]=Integer.class;//ERROR: 因为Integer.class对应的是Integer类型,不是int类型。而Integer.TYPE是指int类型
parameterTypes[1]=double.class;
Method method = cls.getMethod("sum", parameterTypes);
//***1.2.2用obj和method来调用该方法
Object[] args = new Object[2];
args[0] = 10;
args[1] = 2.34;
Object returnObj = method.invoke(obj, args);
System.out.println(returnObj);
}
}

输出结果:

23.4

演示:调用静态方法

Person类加了一个静态方法show();

public static void show(){
System.out.println("show.........");
}

演示类:

package cn.hncu.reflect;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
/**
* 类反射的演示
* @author 陈浩翔
*
* @version 1.0 2016-5-2
*/
public class ReflectOperateObj {
private static final String CLASS_FILE_NAME="cn.hncu.reflect.Person";
public static void main(String[] args) {
try {
callMethod3(CLASS_FILE_NAME);
} catch (ReflectiveOperationException e) {
e.printStackTrace();
}
}
/**
* 四、演示:调用静态方法---不需要对象就可以调,其它的跟普通方法一样
* @param classFileName
* @throws ReflectiveOperationException
*/
private static void callMethod3(String classFileName) throws ReflectiveOperationException{
Class cls = Class.forName(CLASS_FILE_NAME);
//调用static show();
Method methed = cls.getMethod("show", null);
methed.invoke(null, null);
}
}

输出结果:

show.........

* 获取与设置属性值

根据属性名称读取与修改属性的值,访问非静态属性需传入对象为参数。

代码示例:

Person还是之前的类;

现在看演示类:

package cn.hncu.reflect;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
/**
* 类反射的演示
* @author 陈浩翔
*
* @version 1.0 2016-5-2
*/
public class ReflectOperateObj {
private static final String CLASS_FILE_NAME="cn.hncu.reflect.Person";
public static void main(String[] args) {
try {
changeFieldValue(CLASS_FILE_NAME);
} catch (ReflectiveOperationException e) {
e.printStackTrace();
}
}
/**
* 五、演示根据属性名称读取和修改属性的值
* @param classFileName
* @throws ReflectiveOperationException
*/
private static void changeFieldValue(String classFileName) throws ReflectiveOperationException{
Class cls = Class.forName(CLASS_FILE_NAME);
//需求:给一个对象的某属性设置值,如: p.num=123
//1.1必须要用一个类对象
Object obj = cls.newInstance();
//1.2设置该对象的指定属性
//1.2.1先拿到对应的Field对象
Field field = cls.getField("num");//获取属性“num”对应的Field对象
//设置属性值
field.set(obj, 1234);
//读取属性值
System.out.println(field.getInt(obj));//1234----返回的是int类型,如果明确数据类型,用这种更好
System.out.println(field.get(obj));//1234----返回的是Object类型,是通用的
Person p = new Person();
p.num=999;
System.out.println(field.getInt(p));//999,new 谁调谁
}
}

暴力访问其他类的私有方法,私有成员变量,私有构造方法:

Person类加了一个私有方法:abc();

 private int abc(){
System.out.println("abc....");
return 10;
}

演示暴力访问:

package cn.hncu.reflect;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
/**
* 类反射暴力访问其他类的演示
* @author 陈浩翔
*
* @version 1.0 2016-5-2
*/
public class ReflectOperateObj {
private static final String CLASS_FILE_NAME="cn.hncu.reflect.Person";
public static void main(String[] args) {
try {
brokeAccess(CLASS_FILE_NAME);
} catch (ReflectiveOperationException e) {
e.printStackTrace();
}
}
/**
* 六、演示:暴力访问
* @param classFileName
*/
private static void brokeAccess(String classFileName) throws ReflectiveOperationException{
Class cls = Class.forName(CLASS_FILE_NAME);
Object obj = cls.newInstance();
//访问Person中私有的方法abc()
Method m = cls.getDeclaredMethod("abc",null);
//只要打开访问权限的开关,就可以暴力访问了
m.setAccessible(true);
Object returnObj = m.invoke(obj, null);
System.out.println("returnObj= "+returnObj);
//*************
//有关暴力访问的知识点
//其实中要在访问之前调用一下AccessibleObject类中的setAccessible()方法且传入boolean型变量就可以
//而AccessibleObject类是Constructor、Field和Method三个类的父类,因此这三者都能进行暴力访问!
}
}

输出结果:

abc....
returnObj= 10

看,访问到了吧。就算你的类设为私有的,一样能访问,是不是很神奇啊, O(∩_∩)O哈哈~。

练习(模拟Java内省的功能)

* 准备工作 定义一个Model类,里面所有的属性都是private的,然后为每个属性提供getter和setter方法; 再准备一个Map,map的key值都是类里面的属性字段的字符串表示,值任意。

Model类: UserModel :

package cn.hncu.reflect.myBeanUtils;
/**
* @author 陈浩翔
*
* @version 1.0 2016-5-2
*/
public class UserModel {
private String uuid;
private String name;
private int age;
public String getUuid() {
return uuid;
}
public void setUuid(String uuid) {
this.uuid = uuid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((uuid == null) ? 0 : uuid.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
UserModel other = (UserModel) obj;
if (uuid == null) {
if (other.uuid != null)
return false;
} else if (!uuid.equals(other.uuid))
return false;
return true;
}
@Override
public String toString() {
return "UserModel [uuid=" + uuid + ", name=" + name + ", age=" + age
+ "]";
}
}

bookModel:

package cn.hncu.reflect.myBeanUtils;
public class bookModel {
private String uuid;
private String name;
private double inPrice;
private double outPrice;
private int num;
public String getUuid() {
return uuid;
}
public void setUuid(String uuid) {
this.uuid = uuid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getInPrice() {
return inPrice;
}
public void setInPrice(double inPrice) {
this.inPrice = inPrice;
}
public double getOutPrice() {
return outPrice;
}
public void setOutPrice(double outPrice) {
this.outPrice = outPrice;
}
public int getNum() {
return num;
}
public void setNum(int num) {
this.num = num;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((uuid == null) ? 0 : uuid.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
bookModel other = (bookModel) obj;
if (uuid == null) {
if (other.uuid != null)
return false;
} else if (!uuid.equals(other.uuid))
return false;
return true;
}
@Override
public String toString() {
return "bookModel [uuid=" + uuid + ", name=" + name + ", inPrice="
+ inPrice + ", outPrice=" + outPrice + ", num=" + num + "]";
}
}

* 真正的工作 设计一个方法Object getModel(Map map,Class cls),传入一个包含所有值的Map,然后再传入Model类的class,那么返回Model类的实例,这个实例里面已经包含好了所有相关的数据。也就是把Map中的数据通过反射,设置回到Model类实例中。

没有用泛型的(一): MyBeanUtils

package cn.hncu.reflect.myBeanUtils;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Map;
/**
*
* @author 陈浩翔
*
* @version 1.0 2016-5-2
*/
public class MyBeanUtils {
public static Object populate(Class cls,Map map) throws ReflectiveOperationException{
Object obj =null;
//1 用类反射new出对象
obj = (Object) cls.newInstance();
//2 再用类反射对新new的对象设置属性值(必须遵守Java设置规范)--即通过setter方法设置
//2.1遍历出所有该类声明的属性
Field fields[] = cls.getDeclaredFields();
for(Field fld : fields){
//获取该fld对象所代表的属性名
String fldName = fld.getName();
//根据属性名,到map中去读取数据,只有数据非空才需要给该属性设置值
Object mapValue = map.get(fldName);
if(mapValue==null){
//如果map中不存在对应的属性数据,我们在这里给出提示信息
System.out.println(fldName+"的数据为空!");
}else{
//如果map中存在对应的属性数据,则由属性名得出它的setter方法的名字
String setName = "set"+fldName.substring(0, 1).toUpperCase()+fldName.substring(1);
//根据方法名和参数的数据类型(其实就是属性的类型),获得Method对象
Class parameterTypes[] =new Class[1];
parameterTypes[0] = fld.getType();
Method method = cls.getDeclaredMethod(setName, parameterTypes);//最好不要用getMethod,因为这样可能会用到父类的方法
//这里不用担心会访问到私有的,因为权限没放开。
//调用该method对象所代表的方法
Object args[] = new Object[1];
args[0] = mapValue;
method.invoke(obj, args);
}
}
return obj;
}
}

测试类:

package cn.hncu.reflect.myBeanUtils;
import java.util.HashMap;
import java.util.Map;
/**
* @author 陈浩翔
*
* @version 1.0 2016-5-2
*/
public class Client {
public static void main(String[] args) {
test1();
}
private static void test1() {
Map map = new HashMap();
map.put("uuid", "X001");
map.put("name", "阿敏");
map.put("age", 123);
try {
Object userModel = MyBeanUtils.populate(UserModel.class, map);
System.out.println(userModel);
} catch (ReflectiveOperationException e) {
e.printStackTrace();
}
}
}

//这个测试全部都设置了值。 输出结果:

UserModel [uuid=X001, name=阿敏, age=123]

还有可能测试的数据不全。 我们在这里是写了一个输出的(为了看清楚),实际中,是不需要输出的。

package cn.hncu.reflect.myBeanUtils;
import java.util.HashMap;
import java.util.Map;
/**
* @author 陈浩翔
*
* @version 1.0 2016-5-2
*/
public class Client {
public static void main(String[] args) {
test2();
}
private static void test2() {
Map map = new HashMap();
map.put("uuid", "X001");
map.put("name", "阿敏");
try {
Object userModel = MyBeanUtils.populate(UserModel.class, map);
System.out.println(userModel);
} catch (ReflectiveOperationException e) {
e.printStackTrace();
}
}
}

输出结果:

age的数据为空!
UserModel [uuid=X001, name=阿敏, age=0]

为了让那个类通用,我们还测试了bookModel类:

package cn.hncu.reflect.myBeanUtils;
import java.util.HashMap;
import java.util.Map;
/**
* @author 陈浩翔
*
* @version 1.0 2016-5-2
*/
public class Client {
public static void main(String[] args) {
test3();
}
private static void test3() {
Map map = new HashMap();
map.put("uuid", "001");
map.put("name", "红楼梦");
map.put("inPrice", 20.5);
map.put("num", 123);
try {
Object bookModel = MyBeanUtils.populate(bookModel.class, map);
System.out.println(bookModel);
} catch (ReflectiveOperationException e) {
e.printStackTrace();
}
}
}

同样,有一个数据是不全的, 输出结果:

outPrice的数据为空!
bookModel [uuid=001, name=红楼梦, inPrice=20.5, outPrice=0.0, num=123]

如果把数据改全:

private static void test3() {
Map map = new HashMap();
map.put("uuid", "001");
map.put("name", "红楼梦");
map.put("inPrice", 20.5);
//之前没有的数据---outPrice,现在补上
map.put("outPrice", 50.5);
map.put("num", 123);
try {
Object bookModel = MyBeanUtils.populate(bookModel.class, map);
System.out.println(bookModel);
} catch (ReflectiveOperationException e) {
e.printStackTrace();
}
}

输出结果:

bookModel [uuid=001, name=红楼梦, inPrice=20.5, outPrice=50.5, num=123]

好了,测试完全通过。 只是那个工具类有强转,好像不太好,怎么办呢。 这个时候,就可以用泛型了。

下面是用泛型的版本,至于测试,我就只测试一次了。

package cn.hncu.reflect.myBeanUtils;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Map;
public class MyBeanUtils2 {
public static <T>T populate(Class<T> cls,Map<String, Object> map) throws ReflectiveOperationException{
T t = null;
//1 用类反射new出对象
t = cls.newInstance();
//2 再用类反射对新new的对象设置属性值(必须遵守Java设置规范)--即通过setter方法设置
//2.1遍历出所有该类声明的属性
Field flds[] = cls.getDeclaredFields();
for(Field fld:flds){
//获取该fld对象所代表的属性名
String fldName = fld.getName();
Object mapV = map.get(fldName);
//根据属性名,到map中去读取数据,只有数据非空才需要给该属性设置值
if(mapV==null){
//如果map中不存在对应的属性数据,我们在这里给出提示信息
System.out.println(fldName+"数据为空!");
}else{
//如果map中存在对应的属性数据,则由属性名得出它的setter方法的名字
String setName = "set"+fldName.substring(0,1).toUpperCase()+fldName.substring(1);
//根据方法名和参数的数据类型(其实就是属性的类型),获得Method对象
Class parameterTypes[] = new Class[1];
parameterTypes[0] = fld.getType();
Method m = cls.getDeclaredMethod(setName, parameterTypes);
//调用该method对象所代表的方法
Object args[] = new Object[1];
args[0]=mapV;
m.invoke(t, args);
}
}
return t;
}
}

测试类:

package cn.hncu.reflect.myBeanUtils;
import java.util.HashMap;
import java.util.Map;
/**
* @author 陈浩翔
*
* @version 1.0 2016-5-2
*/
public class Client {
public static void main(String[] args) {
test4();
}
private static void test4() {
Map map = new HashMap();
map.put("uuid", "001");
map.put("name", "红楼梦");
map.put("inPrice", 20.5);
//map.put("outPrice", 50.5);
map.put("num", 123);
try {
Object bookModel = MyBeanUtils2.populate(bookModel.class, map);
System.out.println(bookModel);
} catch (ReflectiveOperationException e) {
e.printStackTrace();
}
}
}

输出结果为:

outPrice数据为空!
bookModel [uuid=001, name=红楼梦, inPrice=20.5, outPrice=0.0, num=123]

好了,类反射也就这些内容了。结束啦。 其实类反射也挺容易的,就是通过完整的类名,再调用newInstance方法new一个对象。再通过这个对象来进行操作方法Method,构造方法(调用构造器来new对象 Object initargs[] = new Object[2]; initargs[0] = new String(“Jack”); initargs[1] = new Integer(20); Object resultObj = con.newInstance(initargs);), 成员变量Field。 要访问私有的,只要打开访问权限的开关,就可以暴力访问了 也就是.setAccessible(true);方法,设置为true。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

版权声明
本文为[谙忆]所创,转载请带上原文链接,感谢
https://cloud.tencent.com/developer/article/1777486

  1. 【计算机网络 12(1),尚学堂马士兵Java视频教程
  2. 【程序猿历程,史上最全的Java面试题集锦在这里
  3. 【程序猿历程(1),Javaweb视频教程百度云
  4. Notes on MySQL 45 lectures (1-7)
  5. [computer network 12 (1), Shang Xuetang Ma soldier java video tutorial
  6. The most complete collection of Java interview questions in history is here
  7. [process of program ape (1), JavaWeb video tutorial, baidu cloud
  8. Notes on MySQL 45 lectures (1-7)
  9. 精进 Spring Boot 03:Spring Boot 的配置文件和配置管理,以及用三种方式读取配置文件
  10. Refined spring boot 03: spring boot configuration files and configuration management, and reading configuration files in three ways
  11. 精进 Spring Boot 03:Spring Boot 的配置文件和配置管理,以及用三种方式读取配置文件
  12. Refined spring boot 03: spring boot configuration files and configuration management, and reading configuration files in three ways
  13. 【递归,Java传智播客笔记
  14. [recursion, Java intelligence podcast notes
  15. [adhere to painting for 386 days] the beginning of spring of 24 solar terms
  16. K8S系列第八篇(Service、EndPoints以及高可用kubeadm部署)
  17. K8s Series Part 8 (service, endpoints and high availability kubeadm deployment)
  18. 【重识 HTML (3),350道Java面试真题分享
  19. 【重识 HTML (2),Java并发编程必会的多线程你竟然还不会
  20. 【重识 HTML (1),二本Java小菜鸟4面字节跳动被秒成渣渣
  21. [re recognize HTML (3) and share 350 real Java interview questions
  22. [re recognize HTML (2). Multithreading is a must for Java Concurrent Programming. How dare you not
  23. [re recognize HTML (1), two Java rookies' 4-sided bytes beat and become slag in seconds
  24. 造轮子系列之RPC 1:如何从零开始开发RPC框架
  25. RPC 1: how to develop RPC framework from scratch
  26. 造轮子系列之RPC 1:如何从零开始开发RPC框架
  27. RPC 1: how to develop RPC framework from scratch
  28. 一次性捋清楚吧,对乱糟糟的,Spring事务扩展机制
  29. 一文彻底弄懂如何选择抽象类还是接口,连续四年百度Java岗必问面试题
  30. Redis常用命令
  31. 一双拖鞋引发的血案,狂神说Java系列笔记
  32. 一、mysql基础安装
  33. 一位程序员的独白:尽管我一生坎坷,Java框架面试基础
  34. Clear it all at once. For the messy, spring transaction extension mechanism
  35. A thorough understanding of how to choose abstract classes or interfaces, baidu Java post must ask interview questions for four consecutive years
  36. Redis common commands
  37. A pair of slippers triggered the murder, crazy God said java series notes
  38. 1、 MySQL basic installation
  39. Monologue of a programmer: despite my ups and downs in my life, Java framework is the foundation of interview
  40. 【大厂面试】三面三问Spring循环依赖,请一定要把这篇看完(建议收藏)
  41. 一线互联网企业中,springboot入门项目
  42. 一篇文带你入门SSM框架Spring开发,帮你快速拿Offer
  43. 【面试资料】Java全集、微服务、大数据、数据结构与算法、机器学习知识最全总结,283页pdf
  44. 【leetcode刷题】24.数组中重复的数字——Java版
  45. 【leetcode刷题】23.对称二叉树——Java版
  46. 【leetcode刷题】22.二叉树的中序遍历——Java版
  47. 【leetcode刷题】21.三数之和——Java版
  48. 【leetcode刷题】20.最长回文子串——Java版
  49. 【leetcode刷题】19.回文链表——Java版
  50. 【leetcode刷题】18.反转链表——Java版
  51. 【leetcode刷题】17.相交链表——Java&python版
  52. 【leetcode刷题】16.环形链表——Java版
  53. 【leetcode刷题】15.汉明距离——Java版
  54. 【leetcode刷题】14.找到所有数组中消失的数字——Java版
  55. 【leetcode刷题】13.比特位计数——Java版
  56. oracle控制用户权限命令
  57. 三年Java开发,继阿里,鲁班二期Java架构师
  58. Oracle必须要启动的服务
  59. 万字长文!深入剖析HashMap,Java基础笔试题大全带答案
  60. 一问Kafka就心慌?我却凭着这份,图灵学院vip课程百度云