1

在 Java 中为什么不全部使用 static 方法?

 1 year ago
source link: https://www.v2ex.com/t/867705
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

V2EX  ›  Java

在 Java 中为什么不全部使用 static 方法?

  qiqiqi7001 · 3 小时 8 分钟前 · 2236 次点击

为什么不能全部用 static

51 条回复    2022-07-21 13:55:19 +08:00
chengyiqun

chengyiqun      3 小时 0 分钟前

快进到全民面向过程编程(误
因为 java 是面向对象的, 比如我有个猫类, 里面有个喵喵叫方法.
你要写成全局静态的, 然后给狗狗调用嘛?
paradoxs

paradoxs      2 小时 58 分钟前

xhldtc

xhldtc      2 小时 58 分钟前

因为如果每个方法都是静态的,java 就不会是面向对象的。

您需要在不同的对象上调用方法,因为它们具有不同的状态。

PS:这个问题太基础了,多写点代码就会发现 static 和非 static 方法的区别了
pannanxu

pannanxu      2 小时 58 分钟前

jvm:听我说谢谢你,感谢有你,温暖了四季
Kimen

Kimen      2 小时 55 分钟前

jvm:听我说谢谢你,感谢有你,温暖了四季
xiaofan305

xiaofan305      2 小时 52 分钟前 via Android

个人认为,对于单例对象,是可以全部 static 的。但是 java 的程序多数都需要搞什么依赖注入,方便解耦,统一生命周期管理和一些事件的处理,这时候就不能全部 static 了。如果是自己写的一些小东西,想怎么写都行,不纠结
lmshl

lmshl      2 小时 51 分钟前

这不就是 Rust/Haskell 嘛
当然 Scala 里也可以很轻松实现仅用 static (object method) ,typeclass 风格
理论上在 Java 中只用 static 方法也是可行的,相当于你手动展开 typeclass 调用而已,自己一个人的项目随便怎么玩都行
murmur

murmur      2 小时 51 分钟前   ❤️ 2

这个东西其实就是个编程习惯的问题

比如
Person p1 = new Person(xxx);
Person p2 = new Person(xxxx)
p1.fuck(Person2) //类方法

和 PersonUtil.fuck(p1, p2) //静态方法

用好了其实没什么高下之分
quicksand

quicksand      2 小时 49 分钟前

@murmur 你这个例子怎么带颜色的
kop1989smurf

kop1989smurf      2 小时 48 分钟前

可不可以全部用静态修饰词?当然可以。
好不好?在 java 中这么用不好。

类与对象( class/object ),公共与私有(public/private),静态(static),继承(extends),接口(interface),实现(implements),这是面向对象的核心理念。
这也是你使用 java 这个“面向对象原教旨主义”语言的最大理由之一。
kop1989smurf

kop1989smurf      2 小时 46 分钟前   ❤️ 1

这就像是,你手里又把突击步枪,你说这枪托很硬,我们为什么还要浪费子弹射击呢?用枪托砸人不行么?
当然行,但砸人你为何不用甩棍?
seth19960929

seth19960929      2 小时 43 分钟前

感觉楼上都没说到带你, 我给你说一个实际的.
每个一个对象都有自己的内存地址, 静态的共享内存. 所以本质就是这样.
比如一个 Person 对象要说出自己的名字, 我只用实例化的时候传入名字, say 方法不用管这么多. 直接输出 this.name, 但是静态的话, 你就得考虑怎么实现了.
seth19960929

seth19960929      2 小时 43 分钟前

没说到带你 -> 没说到点
qiqiqi7001

qiqiqi7001      2 小时 43 分钟前

@paradoxs 内存这个问题我知道
1.静态方法在程序开始时生成内存,实例方法在程序运行中生成内存,
所以静态方法可以直接调用,实例方法要先成生实例,通过实例调用方法,静态速度很快,但是多了会占内存。
静态内存是连续的,因为是在程序开始时就生成了,而实例申请的是离散的空间,所以当然没有静态方法快,
而且静态内存是有限制的,太多了程序会启动不了。
但是我还看到另一个结论
2.静态方法和实例方法其实在性能上没有区别,加载时机,和内存占用都一样,调用速度也没有区别。
我想问这两个那个是正确的
murmur

murmur      2 小时 41 分钟前

@seth19960929

Person 只要有 getName 就可以让别人帮你 say 了,这对于 bean 来说几乎是都有的 get 方法
murmur

murmur      2 小时 40 分钟前

我大概明白什么意思了,getName 也不是 static
那 Person 全 static ,数据就得用 Map<String, Object>了
wolfie

wolfie      2 小时 40 分钟前

了解什么是面向对象吗。
Leviathann

Leviathann      2 小时 35 分钟前

听说是因为早期不让 import static
thinkershare

thinkershare      2 小时 34 分钟前

人力是有限的, 状态管理是困难的, 所以我们有了方法执行的上下文, 并限制了在上下文上可执行的操作, 因此有了对象. 你当然可以彻底抛弃对象, 然后将 class 作为 namespace. 那我什么不选择 C 语言呢?
retrocode

retrocode      2 小时 33 分钟前

@murmur #8 其实还是有区别的, 假设 fuck 方法内部有一个 doll 参数, 那 p1/p2.fuck 的 doll, 大概率只是同一厂家不同批次生产的同一型号, 而 PersonUtil.fuck 里的 doll 则从头到尾就是同一个(战术后仰)!
caroline1022

caroline1022      2 小时 32 分钟前

我能想到的一个点是,面向对象的使用方式抽象度更高

比如同样一个让动物叫的功能,你在具体编码的时候无需知道具体场景下过来的是个什么动物,你只需要调用动物.叫()这个方法就行了。每一个不同的动物类别自己去实现叫()这个方法就可以

但如果是静态方法的话,你需要在具体场景中判断如果是个猫得调用 猫.叫(),如果是个狗得调用 狗.叫(),这个耦合度会高得多,更难维护也更容易出问题

比如以后如果来个新的动物,面向对象的话只需要让这个新动物实现叫这个方法就可以,不需要修改业务代码;但如果是静态方法则需要在所有调用叫方法的地方里增加新的判断。
Achieve7

Achieve7      2 小时 31 分钟前

所有的静态方法共享一个内存块儿, 全静态了内存没法管理, 线程一开直接 GG
dqzcwxb

dqzcwxb      2 小时 29 分钟前

对对对,就是要把 jvm 这个小娘们直接塞满
ScepterZ

ScepterZ      2 小时 18 分钟前

如果你是单例的场景,全 static 也不是不行。否则我是真不知道你要咋写代码……
Chinsung

Chinsung      2 小时 18 分钟前

面向对象本身就是为了这个目的去设计的
一个接口,有一个方法是发出叫声
猫实现了这个接口,是喵
狗实现了这个接口,是汪
如果用静态类,那只能
Util.dog 叫(狗)
Util.cat 叫(猫)
这样既要类型检查,能有多少种动物叫就得有多少个方法从名字上区分。
更别说,你如果想要知道这个猫到底能做哪些事,你得找一遍所有静态类,才能知道这个猫被哪些类支持
icyalala

icyalala      2 小时 18 分钟前

static 变量才会在 load class 时分配内存,static 方法在这方面和一般方法可以认为没什么区别。
你大可以全用 static 方法 + 实例变量,把 Java 变成 C 函数 + struct 。
newmlp

newmlp      2 小时 16 分钟前

@qiqiqi7001 所有方法肯定是程序加载的时候就都分配好空间了啊,怎么会有动态生成方法的做法,不管是不是静态方法,方法都是所有实例共享的,但是调用时传的 this 不一样而已
unco020511

unco020511      2 小时 16 分钟前

那你咋面向对象,你都没对象了,咋管理数据和状态?
0x2CA

0x2CA      2 小时 12 分钟前

其实也可以的,你可以使用 ecs 编程方式,实体-组件-系统的方式,这样你方法都是依赖组件的,不关乎什么对象,只要有这个组件的对象都有这个行为,面向数据编程
qiqiqi7001

qiqiqi7001      2 小时 11 分钟前

@newmlp 我啥时候说动态生成方法的做法了,,,,
cpstar

cpstar      2 小时 7 分钟前

有啥不能的,能编译过去,能运行那就是能。
为啥不能的,因为人为设置了条条框框,比如告诉你这个是 OO ,full static method 不叫 OO ,那甭管是 singleton 还是 Util 方式的,叫不叫 OO ?
不要在意这些细节,怎么用的爽怎么来,哪来那么多优雅。
seth19960929

seth19960929      2 小时 4 分钟前

@murmur 是, 设计问题. 你用 map 还得多考虑一次并发问题
xfriday

xfriday      2 小时 2 分钟前

非 static 方法只是把 this 作为隐式参数传递进函数而已
xuboying

xuboying      2 小时 2 分钟前

不懂 Java ,从语言的角度应该没有什么限制吧。
感觉更多的是一个设计模式的问题。(如果是 solo ,那么设计模式其实也没什么纠结的必要了)

举一个 C++新版本里有一个 adhoc 的多态的例子。你说到的问题有一点点相似。有人做了 subtype 多态和 adhoc 的多态的区别比较。认为 subtype 的多态对新派生类更友好,adhoc 的多态对新 method 更友好。所以如果你的使用场景符合维护时会添加更多的 method ,可能写 static 方法会更适合。
qiqiqi7001

qiqiqi7001      1 小时 58 分钟前

@xhldtc 对象不是静态,调用之间都是掉静态方法
oneisall8955

oneisall8955      1 小时 48 分钟前 via Android

多态,接口问题,思考下
siweipancc

siweipancc      1 小时 44 分钟前 via iPhone

gouflv

gouflv      1 小时 39 分钟前 via iPhone

OOP 说了:我要抽象一切

ps:多少静态方法能把 jvm 塞满?
cedoo22

cedoo22      1 小时 27 分钟前

jvm:听我说谢谢你,感谢有你,温暖了四季

全静态,直接变面向过程 /函数编程。
DamonLin

DamonLin      1 小时 26 分钟前

我和你有过这样的疑问哈哈
zhuweiyou

zhuweiyou      1 小时 22 分钟前

可以,操作对象从参数传进去就行了.内存不是问题,加钱就行.
建议你换语言吧
DOLLOR

DOLLOR      1 小时 16 分钟前

object.action()和 action(object)没啥区别,也没有谁比谁更好。
但是因为是 java ,java 主打 OOP ,肯定是能 OOP 的地方就 OOP 呀。
sadfQED2

sadfQED2      1 小时 16 分钟前 via Android

能全部用静态方法啊,我前前前司,一个 java 项目里面,90%都是静态方法。没出任何毛病
darkengine

darkengine      1 小时 13 分钟前

这个方法里需要访问成员变量怎么办?哦,也都声明成静态成员变量是吧。谁家猫狗全都名字一样年龄一样啊。
dzdh

dzdh      1 小时 7 分钟前

@murmur #8

fuck 要判断两个 person 性别是否一致吗
FYFX

FYFX      1 小时 3 分钟前

正如 34 楼所说,最近在看 https://craftinginterpreters.com/representing-code.html#the-expression-problem ,里面提到因为 java 是面向对象的,假定的是你的操作都是基于相似类型的,增加一个新的派生类类会很方便。如果你要全部 static 相当于放弃了 java 的这个特性,但是 java(除了特别新的版本)又没有函数式编程那种好用的模式匹配,你这么做的话会导致不管是加类还是加方法都很麻烦。
min

min      27 分钟前

C++里面为什么需要有 new ?
sun1991

sun1991      25 分钟前

可以全部 static, 没问题.
面向对象编程 vs 面向数据编程.
tabris17

tabris17      24 分钟前

大家冷静听我说:只要我们在 JAVA 中加入动态创建类型的 feature 不就可以了吗 /doge
fox0001

fox0001      19 分钟前 via Android

我觉得,如果全静态,解耦不好做。或者像 go 那样再弄个 wire ?
tairan2006

tairan2006      9 分钟前

全静态你还 OOP 个啥

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK