Java创建FileDownloadListener实例时ProgressListener传参疑问
问题解答
接口类型入参的传入规则
Java中构造方法、普通方法声明参数为接口类型时,传入的实参必须是实现了该接口的类的实例,唯一特殊情况是传入null。Java不允许直接实例化接口本身,不能直接写new ProgressListener()不带实现逻辑。
从你贴的代码可以看到,FileDownloadListener内部对progressListener成员做了非空判断,传null不会触发空指针异常,只是不会执行自定义的进度回调、取消判断逻辑。
该构造方法的设计意图
这是典型的职责分离+装饰器模式实践,核心目的是拆分通用逻辑和可变逻辑,降低使用成本:
FileDownloadListener本身封装了所有和本地文件操作绑定的固定通用逻辑:包括创建文件输出流、读取本地已下载文件长度支持断点续传等,这部分逻辑所有下载到本地文件的场景都通用,不需要调用方重复实现。- 而「进度更新如何展示、下载是否需要终止」是完全可变的个性化逻辑:不同场景下可能需要打印日志、更新UI进度条、响应按钮取消事件,这部分逻辑无法提前统一实现,因此通过接口入参的方式把扩展点开放给调用方自定义。
- 从
FileDownloadListener的方法重写逻辑可以看到,它收到下载进度更新、取消状态查询时,会把调用转交给你传入的ProgressListener实例,相当于帮你屏蔽了所有文件操作的复杂细节,你只需要关心自己的进度处理逻辑即可,不用重写DownloadListener抽象类的全部方法。
正确传参的几种方式
根据你的实际需求选择即可:
- 不需要进度展示、也不需要中途取消下载时,直接传
null即可:
File saveFile = new File("你的本地文件保存路径"); FileDownloadListener listener = new FileDownloadListener(saveFile, null);
- 需要自定义进度处理、取消逻辑时,传入
ProgressListener接口的实现类实例即可,最简便的写法是使用匿名内部类:
// 自定义进度回调逻辑 ProgressListener customCallback = new ProgressListener() { // 自定义取消标记,可通过外部逻辑修改该值触发下载取消 private volatile boolean isCancelled = false; @Override public void updateProgress(long loaded, long total) { // 写入你自己的进度处理逻辑,比如计算百分比、更新UI int progress = total == 0 ? 0 : (int) (loaded * 100 / total); System.out.printf("当前下载进度:%d%%%n", progress); } @Override public boolean hasCancelled() { // 返回取消状态,下载逻辑会定期调用该方法判断是否终止 return isCancelled; } // 对外暴露取消方法,比如绑定UI取消按钮的点击事件 public void cancelDownload() { isCancelled = true; } }; // 传入自定义回调实例 FileDownloadListener listener = new FileDownloadListener(saveFile, customCallback);
- 你也可以传入其他实现了
ProgressListener接口的类实例(包括DownloadListener的其他子类),只要符合接口类型约束都可以正常运行,但一般不需要这么做,匿名内部类已经足够覆盖绝大多数场景。
内容的提问来源于stack exchange,提问作者Znahar
相关产品推荐
相关产品推荐

