泛型类的正确用法
在准备下次直播Java
基础的内容中,偶然看到Java泛型
这个知识点,突然有了点想法,之前一直纠结的一个问题有了解答的思路。
问题:我在多线程任务基类中定义了一个泛型T
的对象t
,但是一直没有找到一个特别合适的发光点,感觉跟重新写一个内部类差别不大,偶尔在匿名类中使用,非但没有更加灵活,反而衍生出一些其他多线程锁的问题。
具体代码如下:
完整的代码地址:「https://github.com/JunManYuanLong/FunTester」
public abstract class ThreadBase<T> extends SourceCode implements Runnable {
····省略代码··· /**
* 用于设置访问资源,用于闭包中无法访问包外实例对象的情况
* @since 2020年10月19日,统一用来设置HTTPrequestbase对象.同样可以用于执行SQL和redis查询语句或者对象,暂未使用dubbo尝试
*/ public T t;
这个t
对象在之前唯一用到的地方就是在标记执行任务的时候用到,把生成的标记(通常是String
类型)赋值到t
中,然后在接下来的过程中访问。但是也仅仅是多了一个存储的地方,实际上标记对象的方法会把标记返回。
突然想到的解决之道是,在除去几种基本类型的多线程任务类(多位abstract
类)属性意外,针对需要引入新的属性的实践任务类,例如RequestThreadTime
、UpdateSqlThread
等多线程任务类中,额外的属性对象就可以用这个泛型T
代替。
突觉自己以前走了很多弯路,对泛型的掌握和应用太浅薄,说干就干了,马上对现有的性能测试框架中的abstract
类和实现类都改一遍。
这里取RequestThreadTimes
为例分享一下代码,有兴趣的同学可以在GitHub
上看到我的提交记录,对比一下前后的修改。
package com.fun.frame.thead; import com.fun.base.constaint.ThreadLimitTimesCount; import com.fun.base.interfaces.MarkThread; import com.fun.frame.httpclient.FanLibrary; import com.fun.frame.httpclient.FunRequest; import com.fun.frame.httpclient.GCThread; import org.apache.http.client.methods.HttpRequestBase; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /**
* http请求多线程类
*/ public class RequestThreadTimes<T extends HttpRequestBase> extends ThreadLimitTimesCount<HttpRequestBase> { static Logger logger = LoggerFactory.getLogger(RequestThreadTimes.class); /**
* 单请求多线程多次任务构造方法
*
* @param request 被执行的请求
* @param times 每个线程运行的次数
*/ public RequestThreadTimes(HttpRequestBase request, int times) { super(request, times, null);
} /**
* 应对对每个请求进行标记的情况
*
* @param request
* @param times
* @param mark
*/ public RequestThreadTimes(HttpRequestBase request, int times, MarkThread mark) { super(request, times, mark);
} protected RequestThreadTimes() { super();
} @Override public void before() { super.before();
GCThread.starts();
} /**
* @throws Exception
*/ @Override protected void doing() throws Exception {
FanLibrary.executeSimlple(t);
} @Override public RequestThreadTimes clone() {
RequestThreadTimes threadTimes = new RequestThreadTimes();
threadTimes.times = this.times;
threadTimes.t = FunRequest.cloneRequest(t);
threadTimes.mark = mark == null ? null : mark.clone(); return threadTimes;
}
}
关于类名那一行,我尝试了很多中办法,包括public class RequestThreadTimes extends ThreadLimitTimesCount {
、public class RequestThreadTimes extends ThreadLimitTimesCount {
、public class RequestThreadTimes extends ThreadLimitTimesCount {
、public class RequestThreadTimes extends ThreadLimitTimesCount {
,然后报出了各种错误,最终我选择了第一种写法,据我粗浅的尝试,被继承的父类中T
可以声明成为HttpRequestBase
类,然后在代码中关于父类的操作,如super(request, times, mark);
中是可以成立的,然后在本类名后面的泛型不能声明对象,只能用限制创建对象是声明泛型的上限。
这里还涉及到一个标记方法中类型转化的修改,如下:
@Override public String mark(ThreadBase threadBase) { if (threadBase instanceof RequestThreadTime) {
RequestThreadTime req = (RequestThreadTime) threadBase; return mark(req.t);
} else if (threadBase instanceof RequestThreadTimes) {
RequestThreadTimes req = (RequestThreadTimes) threadBase; return mark(req.t);
} else {
ParamException.fail(threadBase.getClass().toString());
} return EMPTY;
}