我正在阅读一本关于 jdk6 的令人难以置信的书“java scjp 认证程序员指南”,其中有一节是关于泛型覆盖的。它描述了子签名和覆盖等价物,并描述了我引用的一些覆盖等价物的例子:
Given the following three generic method declarations in a class:
static <T> void merge (MyStack<T> s1, MyStack<T> s2) { /*...*/ }
static <T> void merge (MyStack<T> s1, MyStack<? extends T> s2) { /*...*/ }
static <T> void merge (MyStack<T> s1, MyStack<? super T> s2) { /*...*/ }After erasure, the signature of all three methods is:
merge(MyStack, MyStack)i.e., the signatures of the methods are override-equivalent, hence these methods are not overloaded.
我不完全同意这些方法是覆盖等效的,事实上我认为这些方法有一个“删除的名称冲突”但没有一个是另一个的子签名......可能我错了所以我想对此有所了解。
subsignature 的定义让我觉得它们之间不是subsignatures。
在 JSL 6 #8.4.2 方法签名中 ( http://docs.oracle.com/javase/specs/jls/se6/html/classes.html#8.4.2 )
Two methods have the same signature if they have the same name and argument types. Two method or constructor declarations M and N have the same argument types if all of the following conditions hold:
They. have the same number of formal parameters (possibly zero)
They have the same number of type parameters (possibly zero)
Let
<A1,...,An>be the formal type parameters of M and let<B1,...,Bn>be the formal type parameters of N. After renaming each occurrence of a Bi in N's type to Ai the bounds of corresponding type variables and the argument types of M and N are the same.The signature of a method m1 is a subsignature of the signature of a method m2 if either m2 has the same signature as m1, or the signature of m1 is the same as the erasure of the signature of m2
...Two method signatures m1 and m2 are override-equivalent iff either m1 is a subsignature of m2 or m2 is a subsignature of m1.
在 JSL 8 # 8.4.2 中。方法签名 ( http://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.4.2 )
Two methods or constructors, M and N, have the same signature if they have the same name, the same type parameters (if any) (§8.4.4), and, after adapting the formal parameter types of N to the the type parameters of M, the same formal parameter types.
The signature of a method m1 is a subsignature of the signature of a method m2 if either:
m2 has the same signature as m1, or
the signature of m1 is the same as the erasure of the signature of m2.
Two method signatures m1 and m2 are override-equivalent iff either m1 is a subsignature of m2 or m2 is a subsignature of m1.
简单来说,我怀疑从关于删除的子签名定义我理解 “一个没有删除的签名等于从另一个签名中删除”..而不是 “删除后的两个签名是相等的”..它微妙但重要 (顺便说一下,覆盖等价定义是基于子签名定义的,这就是为什么我要问子签名的原因)
最佳答案
在我看来,这本书的措辞并没有很好地结合在一起。根据 JLS (8.4.9),重载是根据对覆盖等效性的否定来定义的(换句话说:如果存在两个具有相同名称的方法但不是覆盖等效的,那么它们将重载)。
但给出的示例中的方法不是覆盖等效,但DO导致其他原因导致的编译时错误(名称冲突 - JLS 8.4.8.3 中指定的特定编译时错误),因此不要重载。
据我了解,您提出的问题是关于这句话从句的确切语义:
"...or the signature of m1 is the same as the erasure of the signature of m2"
结合
m1 and m2 are override-equivalent iff either m1 is a subsignature of m2 or m2 is a subsignature of m1.
你的书暗示这应该解释为
"or the erasure of the signature of m1 is the same as the erasure of the signature of m2"
(添加的单词以粗斜体显示)。
而你会把它解释为
"or the signature of m1 (without erasure) is the same as the erasure of the signature of m2"
你的解释是正确的。我不认为这句话有歧义,因此我认为以第一种方式解释它(即 删除 两个签名是相同的)是不正确的。你可能喜欢 look at this related answer在这里增加我的意见(我发现它是因为我也想检查我的理解)。
您引用的那本书的部分实际上是在描述重载。
现在 - 当考虑重载时 - JLS (8.4.9) says那:
If two methods of a class (whether both declared in the same class, or both inherited by a class, or one declared and one inherited) have the same name but signatures that are not override-equivalent, then the method name is said to be overloaded.
这至少从 Java 6 开始就是一致的。这就是 override-equivalent 和重载之间的联系的来源。
好的 - 所以你的方法会重载,因为它们不是严格的重写等效的。对吧?
错了。
因为就在那一节的上方in 8.4.8.3, the JLS放入特定的编译时错误:
It is a compile-time error if a type declaration T has a member method m1 and there exists a method m2 declared in T or a supertype of T such that all of the following are true:
m1 and m2 have the same name.
m2 is accessible from T.
The signature of m1 is not a subsignature (§8.4.2) of the signature of m2.
The signature of m1 or some method m1 overrides (directly or indirectly) has the same erasure as the signature of m2 or some method m2 overrides (directly or indirectly).
这是您示例中的场景。就在该部分的下方,它阐明了为什么有必要:
These restrictions are necessary because generics are implemented via erasure. The rule above implies that methods declared in the same class with the same name must have different erasures. It also implies that a type declaration cannot implement or extend two distinct invocations of the same generic interface.
书中的例子很奇怪,因为 Java 不允许覆盖静态方法(子类中方法的签名可以隐藏父类(super class)中的方法)。在我看来,这使得不被覆盖等效的概念对于学习者来说有点棘手。但是,您可以删除 static 并仍然看到他们试图展示的效果。
关于java - 具有相同删除的两种方法不一定是等效的(或者它们之间的签名不是子签名)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31225155/
我的目标是转换表单输入,例如“100兆字节”或“1GB”,并将其转换为我可以存储在数据库中的文件大小(以千字节为单位)。目前,我有这个:defquota_convert@regex=/([0-9]+)(.*)s/@sizes=%w{kilobytemegabytegigabyte}m=self.quota.match(@regex)if@sizes.include?m[2]eval("self.quota=#{m[1]}.#{m[2]}")endend这有效,但前提是输入是倍数(“gigabytes”,而不是“gigabyte”)并且由于使用了eval看起来疯狂不安全。所以,功能正常,
我想安装一个带有一些身份验证的私有(private)Rubygem服务器。我希望能够使用公共(public)Ubuntu服务器托管内部gem。我读到了http://docs.rubygems.org/read/chapter/18.但是那个没有身份验证-如我所见。然后我读到了https://github.com/cwninja/geminabox.但是当我使用基本身份验证(他们在他们的Wiki中有)时,它会提示从我的服务器获取源。所以。如何制作带有身份验证的私有(private)Rubygem服务器?这是不可能的吗?谢谢。编辑:Geminabox问题。我尝试“捆绑”以安装新的gem..
我构建了两个需要相互通信和发送文件的Rails应用程序。例如,一个Rails应用程序会发送请求以查看其他应用程序数据库中的表。然后另一个应用程序将呈现该表的json并将其发回。我还希望一个应用程序将存储在其公共(public)目录中的文本文件发送到另一个应用程序的公共(public)目录。我从来没有做过这样的事情,所以我什至不知道从哪里开始。任何帮助,将不胜感激。谢谢! 最佳答案 无论Rails是什么,几乎所有Web应用程序都有您的要求,大多数现代Web应用程序都需要相互通信。但是有一个小小的理解需要你坚持下去,网站不应直接访问彼此
我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/
在Cooper的书BeginningRuby中,第166页有一个我无法重现的示例。classSongincludeComparableattr_accessor:lengthdef(other)@lengthother.lengthenddefinitialize(song_name,length)@song_name=song_name@length=lengthendenda=Song.new('Rockaroundtheclock',143)b=Song.new('BohemianRhapsody',544)c=Song.new('MinuteWaltz',60)a.betwee
我有一个驼峰式字符串,例如:JustAString。我想按照以下规则形成长度为4的字符串:抓取所有大写字母;如果超过4个大写字母,只保留前4个;如果少于4个大写字母,则将最后大写字母后的字母大写并添加字母,直到长度变为4。以下是可能发生的3种情况:ThisIsMyString将产生TIMS(大写字母);ThisIsOneVeryLongString将产生TIOV(前4个大写字母);MyString将生成MSTR(大写字母+tr大写)。我设法用这个片段解决了前两种情况:str.scan(/[A-Z]/).first(4).join但是,我不太确定如何最好地修改上面的代码片段以处理最后一种
我正在检查一个Rails项目。在ERubyHTML模板页面上,我看到了这样几行:我不明白为什么不这样写:在这种情况下,||=和ifnil?有什么区别? 最佳答案 在这种特殊情况下没有区别,但可能是出于习惯。每当我看到nil?被使用时,它几乎总是使用不当。在Ruby中,很少有东西在逻辑上是假的,只有文字false和nil是。这意味着像if(!x.nil?)这样的代码几乎总是更好地表示为if(x)除非期望x可能是文字false。我会将其切换为||=false,因为它具有相同的结果,但这在很大程度上取决于偏好。唯一的缺点是赋值会在每次运行
我正在尝试使用boilerpipe来自JRuby。我看过guide从JRuby调用Java,并成功地将它与另一个Java包一起使用,但无法弄清楚为什么同样的东西不能用于boilerpipe。我正在尝试基本上从JRuby中执行与此Java等效的操作:URLurl=newURL("http://www.example.com/some-location/index.html");Stringtext=ArticleExtractor.INSTANCE.getText(url);在JRuby中试过这个:require'java'url=java.net.URL.new("http://www
我正在使用Rails3.1并在一个论坛上工作。我有一个名为Topic的模型,每个模型都有许多Post。当用户创建新主题时,他们也应该创建第一个Post。但是,我不确定如何以相同的形式执行此操作。这是我的代码:classTopic:destroyaccepts_nested_attributes_for:postsvalidates_presence_of:titleendclassPost...但这似乎不起作用。有什么想法吗?谢谢! 最佳答案 @Pablo的回答似乎有你需要的一切。但更具体地说...首先改变你View中的这一行对此#
我只想对我一直在思考的这个问题有其他意见,例如我有classuser_controller和classuserclassUserattr_accessor:name,:usernameendclassUserController//dosomethingaboutanythingaboutusersend问题是我的User类中是否应该有逻辑user=User.newuser.do_something(user1)oritshouldbeuser_controller=UserController.newuser_controller.do_something(user1,user2)我