扫码阅读
手机扫码阅读

泛型类的正确用法

62 2024-04-17

在准备下次直播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类)属性意外,针对需要引入新的属性的实践任务类,例如RequestThreadTimeUpdateSqlThread等多线程任务类中,额外的属性对象就可以用这个泛型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;
    } 
原文链接: https://mp.weixin.qq.com/s?__biz=MzU4MTE2NDEyMQ==&mid=2247488269&idx=1&sn=2f243178c90956367ef6e47ada1f5676