mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-05-09 23:51:34 +08:00
add UniqueKeySet
This commit is contained in:
parent
56d490e2ac
commit
8f0f3354e3
@ -2,7 +2,7 @@
|
|||||||
# 🚀Changelog
|
# 🚀Changelog
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------
|
||||||
# 5.7.23 (2022-03-08)
|
# 5.7.23 (2022-03-09)
|
||||||
|
|
||||||
### 🐣新特性
|
### 🐣新特性
|
||||||
* 【http 】 HttpRequest.form采用TableMap方式(issue#I4W427@Gitee)
|
* 【http 】 HttpRequest.form采用TableMap方式(issue#I4W427@Gitee)
|
||||||
@ -10,6 +10,7 @@
|
|||||||
* 【core 】 FileUtil.extName增加对tar.gz特殊处理(issue#I4W5FS@Gitee)
|
* 【core 】 FileUtil.extName增加对tar.gz特殊处理(issue#I4W5FS@Gitee)
|
||||||
* 【crypto 】 增加XXTEA实现(issue#I4WH2X@Gitee)
|
* 【crypto 】 增加XXTEA实现(issue#I4WH2X@Gitee)
|
||||||
* 【core 】 增加Table实现(issue#2179@Github)
|
* 【core 】 增加Table实现(issue#2179@Github)
|
||||||
|
* 【core 】 增加UniqueKeySet(issue#I4WUWR@Gitee)
|
||||||
*
|
*
|
||||||
### 🐞Bug修复
|
### 🐞Bug修复
|
||||||
* 【core 】 修复ObjectUtil.hasNull传入null返回true的问题(pr#555@Gitee)
|
* 【core 】 修复ObjectUtil.hasNull传入null返回true的问题(pr#555@Gitee)
|
||||||
|
@ -0,0 +1,152 @@
|
|||||||
|
package cn.hutool.core.collection;
|
||||||
|
|
||||||
|
import cn.hutool.core.map.MapBuilder;
|
||||||
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.AbstractSet;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 唯一键的Set<br>
|
||||||
|
* 通过自定义唯一键,通过{@link #uniqueGenerator}生成节点对象对应的键作为Map的key,确定唯一<br>
|
||||||
|
* 此Set与HashSet不同的是,HashSet依赖于{@link Object#equals(Object)}确定唯一<br>
|
||||||
|
* 但是很多时候我们无法对对象进行修改,此时在外部定义一个唯一规则,即可完成去重。
|
||||||
|
* <pre>
|
||||||
|
* {@code Set<UniqueTestBean> set = new UniqueKeySet<>(UniqueTestBean::getId);}
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @param <K> 唯一键类型
|
||||||
|
* @param <V> 值对象
|
||||||
|
* @author looly
|
||||||
|
* @since 5.7.23
|
||||||
|
*/
|
||||||
|
public class UniqueKeySet<K, V> extends AbstractSet<V> implements Serializable {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
private Map<K, V> map;
|
||||||
|
private final Function<V, K> uniqueGenerator;
|
||||||
|
|
||||||
|
//region 构造
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造
|
||||||
|
*
|
||||||
|
* @param uniqueGenerator 唯一键生成规则函数,用于生成对象对应的唯一键
|
||||||
|
*/
|
||||||
|
public UniqueKeySet(Function<V, K> uniqueGenerator) {
|
||||||
|
this(false, uniqueGenerator);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造
|
||||||
|
*
|
||||||
|
* @param isLinked 是否保持加入顺序
|
||||||
|
* @param uniqueGenerator 唯一键生成规则函数,用于生成对象对应的唯一键
|
||||||
|
*/
|
||||||
|
public UniqueKeySet(boolean isLinked, Function<V, K> uniqueGenerator) {
|
||||||
|
this(MapBuilder.create(isLinked), uniqueGenerator);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造
|
||||||
|
*
|
||||||
|
* @param initialCapacity 初始容量
|
||||||
|
* @param loadFactor 增长因子
|
||||||
|
* @param uniqueGenerator 唯一键生成规则函数,用于生成对象对应的唯一键
|
||||||
|
*/
|
||||||
|
public UniqueKeySet(int initialCapacity, float loadFactor, Function<V, K> uniqueGenerator) {
|
||||||
|
this(MapBuilder.create(new HashMap<>(initialCapacity, loadFactor)), uniqueGenerator);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造
|
||||||
|
*
|
||||||
|
* @param builder 初始Map,定义了Map类型
|
||||||
|
* @param uniqueGenerator 唯一键生成规则函数,用于生成对象对应的唯一键
|
||||||
|
*/
|
||||||
|
public UniqueKeySet(MapBuilder<K, V> builder, Function<V, K> uniqueGenerator) {
|
||||||
|
this.map = builder.build();
|
||||||
|
this.uniqueGenerator = uniqueGenerator;
|
||||||
|
}
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterator<V> iterator() {
|
||||||
|
return map.values().iterator();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int size() {
|
||||||
|
return map.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return map.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean contains(Object o) {
|
||||||
|
//noinspection unchecked
|
||||||
|
return map.containsKey(this.uniqueGenerator.apply((V) o));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean add(V v) {
|
||||||
|
return null == map.put(this.uniqueGenerator.apply(v), v);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加入值,如果值已经存在,则忽略之
|
||||||
|
*
|
||||||
|
* @param v 值
|
||||||
|
* @return 是否成功加入
|
||||||
|
*/
|
||||||
|
public boolean addIfAbsent(V v) {
|
||||||
|
return null == map.putIfAbsent(this.uniqueGenerator.apply(v), v);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加入集合中所有的值,如果值已经存在,则忽略之
|
||||||
|
*
|
||||||
|
* @param c 集合
|
||||||
|
* @return 是否有一个或多个被加入成功
|
||||||
|
*/
|
||||||
|
public boolean addAllIfAbsent(Collection<? extends V> c) {
|
||||||
|
boolean modified = false;
|
||||||
|
for (V v : c)
|
||||||
|
if (addIfAbsent(v)) {
|
||||||
|
modified = true;
|
||||||
|
}
|
||||||
|
return modified;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean remove(Object o) {
|
||||||
|
//noinspection unchecked
|
||||||
|
return null != map.remove(this.uniqueGenerator.apply((V) o));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clear() {
|
||||||
|
map.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public UniqueKeySet<K, V> clone() {
|
||||||
|
try {
|
||||||
|
UniqueKeySet<K, V> newSet = (UniqueKeySet<K, V>) super.clone();
|
||||||
|
newSet.map = ObjectUtil.clone(this.map);
|
||||||
|
return newSet;
|
||||||
|
} catch (CloneNotSupportedException e) {
|
||||||
|
throw new InternalError(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -3,6 +3,7 @@ package cn.hutool.core.util;
|
|||||||
import cn.hutool.core.annotation.Alias;
|
import cn.hutool.core.annotation.Alias;
|
||||||
import cn.hutool.core.bean.NullWrapperBean;
|
import cn.hutool.core.bean.NullWrapperBean;
|
||||||
import cn.hutool.core.collection.CollUtil;
|
import cn.hutool.core.collection.CollUtil;
|
||||||
|
import cn.hutool.core.collection.UniqueKeySet;
|
||||||
import cn.hutool.core.convert.Convert;
|
import cn.hutool.core.convert.Convert;
|
||||||
import cn.hutool.core.exceptions.UtilException;
|
import cn.hutool.core.exceptions.UtilException;
|
||||||
import cn.hutool.core.lang.Assert;
|
import cn.hutool.core.lang.Assert;
|
||||||
@ -17,6 +18,7 @@ import java.lang.reflect.Field;
|
|||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.util.AbstractMap;
|
import java.util.AbstractMap;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -347,11 +349,12 @@ public class ReflectUtil {
|
|||||||
/**
|
/**
|
||||||
* 是否为父类引用字段<br>
|
* 是否为父类引用字段<br>
|
||||||
* 当字段所在类是对象子类时(对象中定义的非static的class),会自动生成一个以"this$0"为名称的字段,指向父类对象
|
* 当字段所在类是对象子类时(对象中定义的非static的class),会自动生成一个以"this$0"为名称的字段,指向父类对象
|
||||||
|
*
|
||||||
* @param field 字段
|
* @param field 字段
|
||||||
* @return 是否为父类引用字段
|
* @return 是否为父类引用字段
|
||||||
* @since 5.7.20
|
* @since 5.7.20
|
||||||
*/
|
*/
|
||||||
public static boolean isOuterClassField(Field field){
|
public static boolean isOuterClassField(Field field) {
|
||||||
return "this$0".equals(field.getName());
|
return "this$0".equals(field.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -648,40 +651,47 @@ public class ReflectUtil {
|
|||||||
*/
|
*/
|
||||||
public static Method[] getMethods(Class<?> beanClass) throws SecurityException {
|
public static Method[] getMethods(Class<?> beanClass) throws SecurityException {
|
||||||
Assert.notNull(beanClass);
|
Assert.notNull(beanClass);
|
||||||
return METHODS_CACHE.get(beanClass, () -> getMethodsDirectly(beanClass, true));
|
return METHODS_CACHE.get(beanClass,
|
||||||
|
() -> getMethodsDirectly(beanClass, true, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获得一个类中所有方法列表,直接反射获取,无缓存<br>
|
* 获得一个类中所有方法列表,直接反射获取,无缓存<br>
|
||||||
* 接口获取方法和默认方法
|
* 接口获取方法和默认方法,获取的方法包括:
|
||||||
|
* <ul>
|
||||||
|
* <li>本类中的所有方法(包括static方法)</li>
|
||||||
|
* <li>父类中的所有方法(包括static方法)</li>
|
||||||
|
* <li>Object中(包括static方法)</li>
|
||||||
|
* </ul>
|
||||||
*
|
*
|
||||||
* @param beanClass 类或接口
|
* @param beanClass 类或接口
|
||||||
* @param withSupers 是否包括父类或接口的方法列表
|
* @param withSupers 是否包括父类或接口的方法列表
|
||||||
|
* @param withMethodFromObject 是否包括Object中的方法
|
||||||
* @return 方法列表
|
* @return 方法列表
|
||||||
* @throws SecurityException 安全检查异常
|
* @throws SecurityException 安全检查异常
|
||||||
*/
|
*/
|
||||||
public static Method[] getMethodsDirectly(Class<?> beanClass, boolean withSupers) throws SecurityException {
|
public static Method[] getMethodsDirectly(Class<?> beanClass, boolean withSupers, boolean withMethodFromObject) throws SecurityException {
|
||||||
Assert.notNull(beanClass);
|
Assert.notNull(beanClass);
|
||||||
|
|
||||||
if(beanClass.isInterface()){
|
if (beanClass.isInterface()) {
|
||||||
// 对于接口,直接调用Class.getMethods方法获取所有方法,因为接口都是public方法
|
// 对于接口,直接调用Class.getMethods方法获取所有方法,因为接口都是public方法
|
||||||
return withSupers ? beanClass.getMethods() : beanClass.getDeclaredMethods();
|
return withSupers ? beanClass.getMethods() : beanClass.getDeclaredMethods();
|
||||||
}
|
}
|
||||||
|
|
||||||
Method[] allMethods = null;
|
final UniqueKeySet<String, Method> result = new UniqueKeySet<>(true, ReflectUtil::getUniqueKey);
|
||||||
Class<?> searchType = beanClass;
|
Class<?> searchType = beanClass;
|
||||||
Method[] declaredMethods;
|
while (searchType != null) {
|
||||||
while (searchType != null && searchType != Object.class) {
|
if (false == withMethodFromObject && Object.class == searchType) {
|
||||||
declaredMethods = searchType.getDeclaredMethods();
|
break;
|
||||||
if (null == allMethods) {
|
|
||||||
allMethods = declaredMethods;
|
|
||||||
} else {
|
|
||||||
allMethods = ArrayUtil.append(allMethods, declaredMethods);
|
|
||||||
}
|
}
|
||||||
|
result.addAllIfAbsent(Arrays.asList(searchType.getDeclaredMethods()));
|
||||||
|
result.addAllIfAbsent(getDefaultMethodsFromInterface(searchType));
|
||||||
|
|
||||||
|
|
||||||
searchType = (withSupers && false == searchType.isInterface()) ? searchType.getSuperclass() : null;
|
searchType = (withSupers && false == searchType.isInterface()) ? searchType.getSuperclass() : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ArrayUtil.append(allMethods);
|
return result.toArray(new Method[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -777,10 +787,10 @@ public class ReflectUtil {
|
|||||||
|
|
||||||
String name = method.getName();
|
String name = method.getName();
|
||||||
// 跳过getClass这个特殊方法
|
// 跳过getClass这个特殊方法
|
||||||
if("getClass".equals(name)){
|
if ("getClass".equals(name)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if(ignoreCase){
|
if (ignoreCase) {
|
||||||
name = name.toLowerCase();
|
name = name.toLowerCase();
|
||||||
}
|
}
|
||||||
switch (parameterCount) {
|
switch (parameterCount) {
|
||||||
@ -1044,4 +1054,47 @@ public class ReflectUtil {
|
|||||||
}
|
}
|
||||||
return accessibleObject;
|
return accessibleObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取方法的唯一键,结构为:
|
||||||
|
* <pre>
|
||||||
|
* 返回类型#方法名:参数1类型,参数2类型...
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @param method 方法
|
||||||
|
* @return 方法唯一键
|
||||||
|
*/
|
||||||
|
private static String getUniqueKey(Method method) {
|
||||||
|
final StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append(method.getReturnType().getName()).append('#');
|
||||||
|
sb.append(method.getName());
|
||||||
|
Class<?>[] parameters = method.getParameterTypes();
|
||||||
|
for (int i = 0; i < parameters.length; i++) {
|
||||||
|
if (i == 0) {
|
||||||
|
sb.append(':');
|
||||||
|
} else {
|
||||||
|
sb.append(',');
|
||||||
|
}
|
||||||
|
sb.append(parameters[i].getName());
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取类对应接口中的非抽象方法(default方法)
|
||||||
|
*
|
||||||
|
* @param clazz 类
|
||||||
|
* @return 方法列表
|
||||||
|
*/
|
||||||
|
private static List<Method> getDefaultMethodsFromInterface(Class<?> clazz) {
|
||||||
|
List<Method> result = new ArrayList<>();
|
||||||
|
for (Class<?> ifc : clazz.getInterfaces()) {
|
||||||
|
for (Method m : ifc.getMethods()) {
|
||||||
|
if (false == ModifierUtil.isAbstract(m)) {
|
||||||
|
result.add(m);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,34 @@
|
|||||||
|
package cn.hutool.core.collection;
|
||||||
|
|
||||||
|
import cn.hutool.core.lang.Console;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
public class UniqueKeySetTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void addTest(){
|
||||||
|
Set<UniqueTestBean> set = new UniqueKeySet<>(UniqueTestBean::getId);
|
||||||
|
set.add(new UniqueTestBean("id1", "张三", "地球"));
|
||||||
|
set.add(new UniqueTestBean("id2", "李四", "火星"));
|
||||||
|
// id重复,替换之前的元素
|
||||||
|
set.add(new UniqueTestBean("id2", "王五", "木星"));
|
||||||
|
|
||||||
|
// 后两个ID重复
|
||||||
|
Assert.assertEquals(2, set.size());
|
||||||
|
|
||||||
|
set.forEach(Console::log);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@AllArgsConstructor
|
||||||
|
static class UniqueTestBean{
|
||||||
|
private String id;
|
||||||
|
private String name;
|
||||||
|
private String address;
|
||||||
|
}
|
||||||
|
}
|
@ -23,7 +23,7 @@ public class ReflectUtilTest {
|
|||||||
@Test
|
@Test
|
||||||
public void getMethodsTest() {
|
public void getMethodsTest() {
|
||||||
Method[] methods = ReflectUtil.getMethods(ExamInfoDict.class);
|
Method[] methods = ReflectUtil.getMethods(ExamInfoDict.class);
|
||||||
Assert.assertEquals(22, methods.length);
|
Assert.assertEquals(20, methods.length);
|
||||||
|
|
||||||
//过滤器测试
|
//过滤器测试
|
||||||
methods = ReflectUtil.getMethods(ExamInfoDict.class, t -> Integer.class.equals(t.getReturnType()));
|
methods = ReflectUtil.getMethods(ExamInfoDict.class, t -> Integer.class.equals(t.getReturnType()));
|
||||||
@ -35,7 +35,7 @@ public class ReflectUtilTest {
|
|||||||
//null过滤器测试
|
//null过滤器测试
|
||||||
methods = ReflectUtil.getMethods(ExamInfoDict.class, null);
|
methods = ReflectUtil.getMethods(ExamInfoDict.class, null);
|
||||||
|
|
||||||
Assert.assertEquals(22, methods.length);
|
Assert.assertEquals(20, methods.length);
|
||||||
final Method method2 = methods[0];
|
final Method method2 = methods[0];
|
||||||
Assert.assertNotNull(method2);
|
Assert.assertNotNull(method2);
|
||||||
}
|
}
|
||||||
@ -114,7 +114,7 @@ public class ReflectUtilTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Ignore
|
@Ignore
|
||||||
public void getMethodBenchTest(){
|
public void getMethodBenchTest() {
|
||||||
// 预热
|
// 预热
|
||||||
getMethodWithReturnTypeCheck(TestBenchClass.class, false, "getH");
|
getMethodWithReturnTypeCheck(TestBenchClass.class, false, "getH");
|
||||||
|
|
||||||
@ -171,14 +171,26 @@ public class ReflectUtilTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getMethodsFromClassExtends(){
|
public void getMethodsFromClassExtends() {
|
||||||
// 继承情况下,需解决方法去重问题
|
// 继承情况下,需解决方法去重问题
|
||||||
final Method[] methods = ReflectUtil.getMethods(C2.class);
|
Method[] methods = ReflectUtil.getMethods(C2.class);
|
||||||
Assert.assertEquals(2, methods.length);
|
Assert.assertEquals(15, methods.length);
|
||||||
|
|
||||||
|
// 排除Object中的方法
|
||||||
|
// 3个方法包括类
|
||||||
|
methods = ReflectUtil.getMethodsDirectly(C2.class, true, false);
|
||||||
|
Assert.assertEquals(3, methods.length);
|
||||||
|
|
||||||
|
// getA属于本类
|
||||||
|
Assert.assertEquals("public void cn.hutool.core.util.ReflectUtilTest$C2.getA()", methods[0].toString());
|
||||||
|
// getB属于父类
|
||||||
|
Assert.assertEquals("public void cn.hutool.core.util.ReflectUtilTest$C1.getB()", methods[1].toString());
|
||||||
|
// getC属于接口中的默认方法
|
||||||
|
Assert.assertEquals("public default void cn.hutool.core.util.ReflectUtilTest$TestInterface1.getC()", methods[2].toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getMethodsFromInterfaceTest(){
|
public void getMethodsFromInterfaceTest() {
|
||||||
// 对于接口,直接调用Class.getMethods方法获取所有方法,因为接口都是public方法
|
// 对于接口,直接调用Class.getMethods方法获取所有方法,因为接口都是public方法
|
||||||
// 因此此处得到包括TestInterface1、TestInterface2、TestInterface3中一共4个方法
|
// 因此此处得到包括TestInterface1、TestInterface2、TestInterface3中一共4个方法
|
||||||
final Method[] methods = ReflectUtil.getMethods(TestInterface3.class);
|
final Method[] methods = ReflectUtil.getMethods(TestInterface3.class);
|
||||||
@ -189,25 +201,26 @@ public class ReflectUtilTest {
|
|||||||
Assert.assertArrayEquals(methods, publicMethods);
|
Assert.assertArrayEquals(methods, publicMethods);
|
||||||
}
|
}
|
||||||
|
|
||||||
interface TestInterface1{
|
interface TestInterface1 {
|
||||||
void getA();
|
void getA();
|
||||||
|
|
||||||
void getB();
|
void getB();
|
||||||
|
|
||||||
default void getC(){
|
default void getC() {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
interface TestInterface2 extends TestInterface1{
|
interface TestInterface2 extends TestInterface1 {
|
||||||
@Override
|
@Override
|
||||||
void getB();
|
void getB();
|
||||||
}
|
}
|
||||||
|
|
||||||
interface TestInterface3 extends TestInterface2{
|
interface TestInterface3 extends TestInterface2 {
|
||||||
void get3();
|
void get3();
|
||||||
}
|
}
|
||||||
|
|
||||||
class C1 implements TestInterface2{
|
class C1 implements TestInterface2 {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void getA() {
|
public void getA() {
|
||||||
@ -220,7 +233,7 @@ public class ReflectUtilTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class C2 extends C1{
|
class C2 extends C1 {
|
||||||
@Override
|
@Override
|
||||||
public void getA() {
|
public void getA() {
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user