既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上大数据知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.logging.Level;
/\*\*
\* 抽象类Logger的子类:输出日志到文件中
\* @author yanliang
\* @date 9/28/2020 4:44 PM
\*/
public class FileLogger extends Logger {
private Writer fileWriter;
public FileLogger(String name, boolean enabled, Level minPermittedLevel, String filePath) throws IOException {
super(name, enabled, minPermittedLevel);
this.fileWriter = new FileWriter(filePath);
}
@Override
protected void doLog(Level level, String message) {
// 格式化level 和 message,输出到日志文件
fileWriter.write(...);
}
}
MessageQueuLogger
import java.util.logging.Level;
/\*\*
\* 抽象类Logger的子类:输出日志到消息队列中
\* @author yanliang
\* @date 9/28/2020 6:39 PM
\*/
public class MessageQueueLogger extends Logger {
private MessageQueueClient messageQueueClient;
public MessageQueueLogger(String name, boolean enabled, Level minPermittedLevel, MessageQueueClient messageQueueClient) {
super(name, enabled, minPermittedLevel);
this.messageQueueClient = messageQueueClient;
}
@Override
protected void doLog(Level level, String message) {
// 格式化level 和 message,输出到消息队列中
messageQueueClient.send(...)
}
}
通过上面的例子,我们来看下抽象类有哪些特性。
- 抽象类不能被实例化,只能被继承。(new 一个抽象类,会报编译错误)
- 抽象类可以包含属性和方法。方法既可以包含实现,也可以不包含实现。不包含实现的方法叫做抽象方法
- 子类继承抽象类,必须实现抽象类中的所有抽象方法。
接口
同样的,下面我们通过一个例子来看下接口的使用场景。
/\*\*
\* 过滤器接口
\* @author yanliang
\* @date 9/28/2020 6:46 PM
\*/
public interface Filter {
void doFilter(RpcRequest req) throws RpcException;
}
/\*\*
\* 接口实现类:鉴权过滤器
\* @author yanliang
\* @date 9/28/2020 6:48 PM
\*/
public class AuthencationFilter implements Filter {
@Override
public void doFilter(RpcRequest req) throws RpcException {
// 鉴权逻辑
}
}
/\*\*
\* 接口实现类:限流过滤器
\* @author yanliang
\* @date 9/28/2020 6:48 PM
\*/
public class RateLimitFilter implements Filter{
@Override
public void doFilter(RpcRequest req) throws RpcException {
// 限流逻辑
}
}
/\*\*
\* 过滤器使用demo
\* @author yanliang
\* @date 9/28/2020 6:48 PM
\*/
public class Application {
// 过滤器列表
private List<Filter> filters = new ArrayList<>();
filters.add(new AuthencationFilter());
filters.add(new RateLimitFilter());
public void handleRpcRequest(RpcRequest req) {
try {
for (Filter filter : filters) {
filter.doFilter(req);
}
} catch (RpcException e) {
// 处理过滤结果
}
// ...
}
}
上面的案例是一个典型的接口使用场景。通过Java中的 interface 关键字定义了一个Filter 接口,AuthencationFilter 和 RetaLimitFilter 是接口的两个实现类,分别实现了对Rpc请求的鉴权和限流的过滤功能。
下面我们来看下接口的特性:
- 接口不能包含属性(也就是成员变量)
- 接口只能生命方法,方法不能包含代码实现
- 类实现接口时,必须实现接口中生命的所有方法。
综上,从语法上对比,这两者有比较大的区别,比如抽象类中可以定义属性、方法的实现,而接口中不能定义属性,方法也不能包含实现等。
除了语法特性的不同外,从设计的角度,这两者也有较大区别。抽象类本质上就是类,只不过是一种特殊的类,这种类不能被实例化,只能被子类继承。属于is-a的关系。接口则是 has-a 的关系,表示具有某些功能。对于接口,有一个更形象的叫法:协议(contract)
抽象类和接口解决了什么问题?
下面我们先来思考一个问题~
抽象类的存在意义是为了解决代码复用的问题(多个子类可以继承抽象类中定义的属性哈方法,避免在子类中,重复编写相同的代码)。
那么,既然继承本身就能达到代码复用的目的,而且继承也不一定非要求是抽象类。我们不适用抽象类,貌似也可以实现继承和复用。从这个角度上讲,我们好像并不需要抽象类这种语法呀。那抽象类除了解决代码复用的问题,还有其他存在的意义吗?
这里大家可以先思考一下哈~
我们还是借用上面Logger的例子,首先对上面的案例实现做一些改造。在改造之后的实现中,Logger不再是抽象类,只是一个普通的父类,删除了Logger中的两个方法,新增了 isLoggable()方法。FileLogger 和 MessageQueueLogger 还是继承Logger父类已达到代码复用的目的。具体代码如下:
/\*\*
\* 父类:非抽象类,就是普通的类
\* @author yanliang
\* @date 9/27/2020 5:59 PM
\*/
public class Logger {
private String name;
private boolean enabled;
private Level minPermittedLevel;
public Logger(String name, boolean enabled, Level minPermittedLevel) {
this.name = name;
this.enabled = enabled;
this.minPermittedLevel = minPermittedLevel;
}
public boolean isLoggable(Level level) {
return enabled && (minPermittedLevel.intValue() <= level.intValue());
}
}
/\*\*
\* 抽象类Logger的子类:输出日志到文件中
\* @author yanliang
\* @date 9/28/2020 4:44 PM
\*/
public class FileLogger extends Logger {
private Writer fileWriter;
public FileLogger(String name, boolean enabled, Level minPermittedLevel, String filePath) throws IOException {
super(name, enabled, minPermittedLevel);
this.fileWriter = new FileWriter(filePath);
}
protected void log(Level level, String message) {
if (!isLoggable(level)) return ;
// 格式化level 和 message,输出到日志文件
fileWriter.write(...);
}
}
package com.yanliang.note.java.abstract_demo;
import java.util.logging.Level;
/\*\*
\* 抽象类Logger的子类:输出日志到消息队列中
\* @author yanliang
\* @date 9/28/2020 6:39 PM
\*/
public class MessageQueueLogger extends Logger {
private MessageQueueClient messageQueueClient;
public MessageQueueLogger(String name, boolean enabled, Level minPermittedLevel, MessageQueueClient messageQueueClient) {
super(name, enabled, minPermittedLevel);
this.messageQueueClient = messageQueueClient;
}
protected void log(Level level, String message) {
if (!isLoggable(level)) return ;
// 格式化level 和 message,输出到消息队列中
messageQueueClient.send(...)
}
}
以上实现虽然达到了代码复用的目的(复用了父类中的属性),但是却无法使用多态的特性了。
像下面这样编写代码就会出现编译错误,因为Logger中并没有定义log()方法。
![img](https://img-blog.csdnimg.cn/img_convert/0d0d963e8d602057d970a8fe17e155c1.png)
![img](https://img-blog.csdnimg.cn/img_convert/6e3d571c482bcadfedf24767ec36e7f6.png)
**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**
**[需要这份系统化资料的朋友,可以戳这里获取](https://bbs.csdn.net/topics/618545628)**
**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**
..(img-7GZAvcQF-1715738692554)]
**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**
**[需要这份系统化资料的朋友,可以戳这里获取](https://bbs.csdn.net/topics/618545628)**
**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**