Java泛型使用建议(List T、List ?、List Object的使用建议)

Java泛型使用建议(List T、List ?、List Object的使用建议)

泛型在用法上可以分成泛型类和泛型方法两种:

泛型类

泛型类在实例化时就要指明类型,不同的类型实例必须要重新new一次,不够灵活

泛型接口interface Request

* 1.接口中有方法,且引用了泛型T时,class SubRequest implements Request

* 父子都要有否则不能编译,因为实现的方法中有T

* 2.接口中没有方法,以下三种定义都可以,第三种相当字面T改成了字面M

* class SubRequest implements Request

* class SubRequest implements Request、

* class SubRequest implements Request

* 3.子类新增泛型

* class SubRequest implements Request

泛型方法

定义泛型方法时,必须在返回值前加上,声明该方法是泛型方法,泛型方法在调用时指明类型,比较灵活,如果泛型方法返回泛型类型时,方法返回时要强转为泛型类型,调用方直接用真实类型接收

// 无返回值

public static void test(T t) {

System.out.println(t.getClass());

}

// 有返回值

User user = test();

System.out.println(user);

public static T test() {

Object user = new User();

return (T) user;

}

泛型方法的真实案例,可以点击这里查看,基于CountDownLatch的单元测试并发工具类,此案例在实际工作中可以用到,另外我实现了一套泛型的内存队列,写这篇博客也是想总结一下用法,给迷茫的人一些启示。

Class、Class、Class、Class< T>的应用

* 泛型类

* public interface Request {

void serialize(T t);

}

* 声明对象方式:Request request、Request request,serialize方法的参数T可以是任意类型

* 声明对象方式:Request request,调用serialize方法,任意类型的参数都不会编译成功

* 声明对象方式:Request request,serialize方法的参数T只能是String

* 泛型方法

* void doWork(V v){

* }

* V doWork(){

* return (V) null;

* }

* 方法参数V相当于Object,可以是任意类型

List、List、List的选择

List、List、List这三者都可以容纳所有的对象,但使用的顺序应该是首选List,次之List,最后选择List,原因如下:

List是确定的某一个类型,具体类型在运行期决定;List表示的是任意类型;List表示List集合中的所有元素都是Object类型;List可以进行读写操作,例如add、remove等操作,因为它的类型是固定的,编码期不需要进行任何的转型操作。List是只读类型,不能进行增加/修改操作,因为编译器不知道真实类型,无法校验类型是否安全,而且它读出的元素都是Object类型的,需要主动转型,所以它经常用于泛型方法的返回值。List虽然不能增加、修改元素,但是可以删除元素,例如remove、clear方法,因为删除和泛型类型无关。List也可以读写操作,但是它执行写入时需要向上转型,在读取数据后,需要向下转型,而此时已经失去了泛型存在的意义。

? extends E和? super E什么时候用

泛型结构只参与“读”操作则限定上界(extends关键字),例如下面idea生成的for循环代码,直接使用Integer表示

public static void read1(List list) {

for (Integer integer : list) {

}

}

泛型结构只参与“写”操作则限定下界(super关键字),例如下面idea生成的for循环代码,直接使用Object表示

public static void read(List list) {

for (Object o : list) {

}

}

泛型方法的应用

public final class MapControl {

private MapControl() {

}

/**

* 单例

*/

private static final MapControl mapControl;

/**

* 数据,实际应用中可以把这个当成RedisTemplate

* Map map; 这种声明是错误的,成员变量中不能出现类上没有定义的泛型

*/

private static final Map map;

/**

* 控制并发20

*/

private static final Semaphore semaphore;

static {

mapControl = new MapControl();

map = new ConcurrentHashMap<>();

semaphore = new Semaphore(20);

}

private static Map getMap() {

try {

semaphore.acquire();

return map;

} catch (Exception e) {

throw new IllegalStateException(e);

}

}

public static void release() {

semaphore.release();

}

private static Object execute(Statement statement) {

try {

Map map = MapControl.getMap();

return statement.prepare(map);

} finally {

release();

}

}

interface Statement {

/**

* 方法返回Object更具有统一性,因为不确定返回数据的的类型,例如方法返回V,返回List,返回Map

* 所以返回Object可以兼容一切返回类型,再强转为需要的类型

*

* @param map

* @return

*/

Object prepare(final Map map);

}

public static void set(final K key, final V value) {

MapControl.execute(new MapControl.Statement() {

@Override

public V prepare(Map map) {

map.put(key, value);

return null;

}

});

}

public static V get(final K key) {

/**

* 返回时强转为V

*/

return (V) MapControl.execute(new Statement() {

@Override

public V prepare(Map map) {

return map.get(key);

}

});

}

public static Map getAll(final List keys) {

/**

* 返回时强转为Map类型

*/

Map result = (Map) MapControl.execute(new Statement() {

@Override

public Object prepare(Map map) {

Map result = new HashMap<>();

for (K k : keys) {

result.put(k, map.get(k));

}

return result;

}

});

return result;

}

public static void main(String[] args) {

MapControl.set(1, "1");

MapControl.set("name", "p7+");

Object obj = new Object();

MapControl.set(obj, obj);

MapControl.set(2, 2);

MapControl.set(3, 3);

MapControl.set(4, 4);

MapControl.set("name1", "name1");

MapControl.set("name2", "name2");

String v = MapControl.get(1);

System.out.println(v);

System.out.println(MapControl.get("1"));

System.out.println(MapControl.get("name"));

System.out.println(MapControl.get(obj));

List keys = new ArrayList<>();

keys.add(2);

keys.add(3);

keys.add(4);

System.out.println(MapControl.getAll(keys));

List strKeys = new ArrayList<>();

strKeys.add("name");

strKeys.add("name1");

strKeys.add("name2");

System.out.println(MapControl.getAll(strKeys));

}

}

相关推荐

VFP的主要含义
约彩365苹果在线安装

VFP的主要含义

📅 07-30 👁️ 4147
USDT中omni和erc20、trc20的对比转账到账时间和安全性等对比
阴阳师神龛商店妖刀姬值得换妖吗
外勤365官方网站

阴阳师神龛商店妖刀姬值得换妖吗

📅 07-06 👁️ 1391
监狱警长职级对照表图(监狱警察职务级别)
外勤365官方网站

监狱警长职级对照表图(监狱警察职务级别)

📅 09-03 👁️ 3923
諂的部首
约彩365苹果在线安装

諂的部首

📅 09-19 👁️ 6099
图标遮罩
office365登陆账号没有反应

图标遮罩

📅 08-18 👁️ 4620