Java 中, new 对象时,用接口作为接收变量到底有什么好处呢?

2019-08-16 14:03:46 +08:00
 Wangjl

这个问题百度了很多一直也没看明白,百度上各种文章写的也不太清晰。

有没有通俗易懂白话,来讲讲到底有什么好处

例如

接口类型 变量 = new 实现类();

实现类类型 变量 = new 实现类();
8228 次点击
所在节点    Java
80 条回复
kkkkkrua
2019-08-16 16:41:49 +08:00
私有变量没啥用
Vtwoguest
2019-08-16 17:24:25 +08:00
很类似于职场的中庸之道 就是什么事情都模模糊糊
例如:
你工资多少? 不太多 也就那样
你感觉谁漂亮? 都还行 我看不出来
你觉得那个人怎么样? 还行
stevenkang
2019-08-16 17:30:58 +08:00
====== 抽象类 ======
C2 可以开自动挡,C1 不仅可以开自动挡。这时候我们理解为 C2 或者 C2 以及以上的,均可以开自动挡,这就是抽象类(不用管你是 C1 还是 C2,只要是 C2 以及以上,均可以调用开自动挡)

====== 接口 ======
C2 和 C1 都是驾照(实现了驾照接口),然后有驾照都可以开车,于是:
驾照 jz1 = new C1 ()
驾照 jz2 = new C2 ()

jz1.可以开车()
jz2.可以开车()

====== 总结 ======
有了抽象类和接口的概念,对于交警(使用者)来说,不用管你具体实现是考的 C1 还是 C2,是不是很方便?
CEBBCAT
2019-08-16 17:34:08 +08:00
你要是存到实现类里,那你搞接口可不就是脱裤子放屁吗?
tabris17
2019-08-16 17:36:30 +08:00
为了实现多态
luozic
2019-08-16 17:44:34 +08:00
解耦合,并且有助于封装子功能模块。
npe
2019-08-16 17:52:11 +08:00
约定俗成,面向接口开发。
cs419
2019-08-16 17:52:52 +08:00
接口是在可变时, 意义大
之后没有多态化,那只能看成是种仪式感

fun getCar(){ // 比如此时 car 可变
Car car = null;
if(...) car = new CarA();
if(...) car = new CarB();
if(...) car = new CarC();
return car;
}

// 如果 是某个方法的返回值 则 car 是多态
Car car = getCar();

// 如果作为参数传给方法 Call(Car c)时 也能达到多态的目的
而 Call(CarA c) 显然是不行的

回头谈楼主的示例
那可以说更多是仪式感
Car car = new Car();
car.run();
passerbytiny
2019-08-16 17:58:15 +08:00
首先排除以下情形:类似于 Service、ServiceImpl 这种,接口-实现一一对应的定义,此时将变量类型定义为接口而不是实现类纯粹是一种约定。

上述情形被批判的程度,仅次于贫血领域模型,二者都属于拍脑袋设计+回到过程编程的返祖设计,连过度设计都算不上。

至于用“接口类型”而不是“实现类类型”定义变量的原因,不是因为有好处,而是因为你要的就是一个“接口类型”的变量。如果你明确的要一个“实现类类型”的变量,那你就该定义成“实现类类型”变量。但通常你想要的只是一个接口的实例而不是类的实例,那么你就应该精确的定义成“接口类型”变量。

举例来说:如果你想要一个“列表”,那么就要“ List a = new ArrayList()”或者“ List a = new LinkedList()”;如果你非常精确的想要一个“数组列表”,那么就要“ ArrayList a = new ArrayList()”。

另外,接口类型 /基类 变量 = new 实现类 /子类(); 这种形式,是多态的一个点。前几楼那些认为过度设计的真是暴漏智商了,“多态”这个面向对象基本特性都不知道。
HangoX
2019-08-16 18:24:29 +08:00
最少依赖原则啊,我只要接口的内容就够了,不需要其他内容,就用接口即可,当替换实现的时候就不蛋疼了
Sasasu
2019-08-16 21:10:01 +08:00
为了让软件运行缓慢,方便优化。

接口隐藏了实际算法的复杂度,继续用楼上的例子,linked list 和 array list。
Java 的 linked list 支持随机访问,一个返回 list 实际上是 linked list 的接口会埋下产生巨大复杂度的隐患。这样日报里就可以写 “经过一天的排查,修复了一个运行缓慢的算法,压测性能提升 60%”。


ServletRequest 到现在也只有一个 HttpServletRequest 还一般是阻塞的。
JDBC 只规定了同步接口,导致整个 Java 的异步生态被锁死在线程池写数据库里。
还有人记得 javax 里面的一堆接口么?
iPhoneXI
2019-08-16 22:05:33 +08:00
毕竟喜欢 Python,Golang 的接口设计
Python 是鸭子类型,
iPhoneXI
2019-08-16 22:06:50 +08:00
@iPhoneXI Golang 也类似,实现了 interface 的所有方法就行
wenmingvs
2019-08-16 23:39:36 +08:00
设计模式六大原则之一,依赖倒置
hantsy
2019-08-16 23:51:35 +08:00
不是应该这样写吗,var list=List.of(1,2,3)
lhx2008
2019-08-17 00:17:16 +08:00
@passerbytiny ServiceImpl 有没有可能是当初 IOC 的锅?其实现在完全没有必要这样设计了。
francis59
2019-08-17 01:15:17 +08:00
依赖于接口相当于服务使用方和提供方的一种约定,只使用约定好的接口里的方法,这样更换服务提供方就不那么蛋疼了,而如果依赖于具体实现,想想要是每种服务提供方的方法(方法名、参数、返回值等等)都不一样,或者用了某种实现独有的方法,那更换实现就真蛋疼了
nguoidiqua
2019-08-17 01:29:01 +08:00
原因很简单,一些不同的类有同样的方法,但方法效果不同。

我现在要把这一堆不同的类当作参数丢到某个方法里面去调用这个方法。

赋值给接口的话,你就不用去做区分处理了,这个和赋给父类差不多。
billlee
2019-08-17 01:41:07 +08:00
局部变量的话,没有卵用。新一点的 kotlin/scala 都可以自动推导了。
20015jjw
2019-08-17 07:09:36 +08:00
好恐怖回国要是面试上面的乱七八糟术语都看不懂- -

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/592462

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX