Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java继承,扩展类如何影响实际类_Java_Inheritance_Final - Fatal编程技术网

Java继承,扩展类如何影响实际类

Java继承,扩展类如何影响实际类,java,inheritance,final,Java,Inheritance,Final,我正在复习Sun认证学习指南,其中有一段描述了最终修改器。上面说 “如果程序员可以自由地扩展我们所知道的字符串类文明,它可能会崩溃” 他是什么意思? 如果可以扩展字符串类。。。我不会有一个名为MyString的类继承所有字符串属性。 仅仅通过扩展字符串类,如何以任何方式更改实际的字符串类 非常感谢您的回答扩展类不会影响基类。但是,它可能会影响基类的使用者 假设您能够扩展字符串,您可以编写如下内容: class MyString extends String { @Override

我正在复习Sun认证学习指南,其中有一段描述了最终修改器。上面说

“如果程序员可以自由地扩展我们所知道的字符串类文明,它可能会崩溃”

他是什么意思? 如果可以扩展字符串类。。。我不会有一个名为MyString的类继承所有字符串属性。 仅仅通过扩展字符串类,如何以任何方式更改实际的字符串类


非常感谢您的回答

扩展类不会影响基类。但是,它可能会影响基类的使用者

假设您能够扩展
字符串
,您可以编写如下内容:

class MyString extends String {

    @Override
    public int length() {
        System.exit();
    }
}

现在,将这个类传递给任何使用字符串的对象,很可能会很快退出程序。这不是文明的终结,但你可以做一些更邪恶的事情。

好吧,一个问题是,如果你可以将String类子类化,你很可能会以多种方式破坏jvm的安全性。许多权限检查各种字符串值以确定是否允许给定的操作。如果您的代码提供字符串值,那么您可以返回一个字符串实例,当安全管理器查看该实例时,该实例将被“签出”,但稍后的行为将像一个完全不同的值

例如,假设您有一些敏感的jvm范围的配置:

public static void registerProvider(String providerName, Provider impl) {
  SecurityManager sm = ...;
  if(sm != null) {
    // say the check provider method doesn't allow strings starting with "com.sun."
    sm.checkProvider(providerName);
  }
  _providerMap.put(providerName, impl);
}
现在,我实现了一个自定义字符串,它覆盖
startsWith()
方法,如果传递值
“com.sun.”
,则返回
false
,但我的字符串的实际值以
com.sun.
开头


当然,更不用说字符串是不可变的,如果字符串被破坏,可能会导致各种各样的破坏(如其他答案中更详细地提到的)。

考虑到在整个Java API中,您将看到如下构造:

HashMap<String, Object> map;
HashMap;
它使用字符串进行索引。这是一个非常常见的问题,例如属性和-在安全相关的地方,这可能是最糟糕的。此代码依赖未修改的
字符串
来保持安全

但是现在让您修改的
String
类允许在适当的位置反转字符串

然后我们所知道的世界就会崩溃,因为到处的地图都会变得一团糟。日志记录会崩溃,等等


很多代码依赖于
字符串
类是不可变的
,那么,如果它真的是不可变的,您还想在它上面添加什么功能呢?

扩展类根本不会影响类。但是,由于任何继承类也是基类,因此它应该遵守基类的行为契约。如果程序员要更改常见的框架类型,那么您就不能指望这些类按预期工作。因此,您希望防止滥用此类类的选项—这是通过使用final关键字来实现的。

夸张的灾难可能是指字符串(im)可变性的安全方面。字符串通常作为参数传递给各种I/O资源连接API(例如JDBC和文件I/O)。这样的字符串通常是资源定位器和身份验证凭据的串联,并且该API将在返回连接之前执行检查以确保凭据对请求的资源有效如果字符串是可变的,它将为所有类型的安全漏洞打开网关作为资源指针/地址(例如数据库连接的数据库名或包含用户敏感信息的文件名)可以在身份验证成功后但在为请求的原始资源建立资源连接之前进行修改,从而导致未经授权的访问和破坏访问控制


使字符串不可变的另一个原因是使其线程安全。

实际上,问题与扩展
String
或任何其他类无关

问题实际上在于Java本身。问题在于,您无法在其代码中实际定义特定对象实现的契约。实际上,
String
的代码中没有说明它是不可变的,因为不能指定不可变性,只能对它进行编码。该契约仅产生于
String
的实际实现

如果可以用Java语言声明
String
Number
Integer
等是不可变的,那么我们就不需要将这些类设置为final。在我看来,这是一种削弱Java能力的疾病,您无法在代码中定义契约。您只能对其进行编码和记录


我希望能够扩展字符串并定义一个
UppercaseString扩展字符串
,但Java中没有
契约(不可变,内部)
关键字,所以我不能这样做,因为要最接近这个契约,唯一可用的关键字是
final
,而不是应该的
immutable

听起来有点像hyperbolic@mre是的,但考虑到它在认证考试中,这真是太令人敬畏了@drlobo我认为您应该将这个问题的标题改为:“为什么Sun认证研究指南认为扩展字符串类会导致文明崩溃?”改变行为的可能重复不能使不变性约束失效。想象一个类
ReversedString
,它有一个方便的构造函数。@jeppi你可以用一个静态方法来做这件事,实际上根本不需要一个新的类。在某些情况下,你更喜欢构造函数而不是静态工厂方法。五月