标签: effective-java

这个类是完全不可变的吗?

我正在尝试按照Effective Java Item 15(Minimize Mutability)中给出的建议将可变类转换为Immutable类.谁能告诉我我创建的类是否完全不可变?

可变类

public class Record {
    public int sequenceNumber;
    public String id;
    public List<Field> fields;

    /**
     * Default Constructor
     */
    public Record() {
        super();
    }

    public Record addField(Field fieldToAdd) {
        fields.add(fieldToAdd);
        return this;
    }

    public Record removeField(Field fieldToRemove) {
        fields.remove(fieldToRemove);
        return this;
    }

    public int getSequenceNumber() {
        return sequenceNumber;
    }

    public String getId() {
        return id;
    }

    public List<Field> getFields() {
        return fields;
    }

    public void setSequenceNumber(int sequenceNumber) {
        this.sequenceNumber = sequenceNumber;
    }

    public void setFields(List<Field> …
Run Code Online (Sandbox Code Playgroud)

java immutability effective-java

4
推荐指数
1
解决办法
452
查看次数

需要我让所有类都不可变吗?

我读了Effective Java,并写了

如果一个类不能成为不可变的,尽可能地限制它的可变性......

......除非有令人信服的理由使其成为非最终的,否则每个领域都是最终的.

所以需要我总是让我所有的POJO(例如简单的Book带班ID,TitleAuthor域)班不变?当我想要改变我的对象的状态时(例如用户在代表很多书的表中更改它),而不是setter使用这样的方法:

public Book changeAuthor(String author) {
   return new Book(this.id, this.title, author);  //Book constructor is private
}
Run Code Online (Sandbox Code Playgroud)

但我的事情真的不是好主意..

请解释我何时使类不可变.

java immutability effective-java

4
推荐指数
1
解决办法
479
查看次数

什么是标量类型,为什么将未经检查的强制转换抑制为数组类型而不是标量类型风险更大?

来自Effective Java Item 26 偏好通用类型

在所有其他条件相同的情况下,将未经检查的强制转换抑制为数组类型而不是标量类型风险更大,这表明第二种解决方案.但是在一个比Stack更实际的泛型类中,你可能会在代码中的许多点读取数组,因此选择第二个解决方案需要多次转换为E而不是单个转换为E [],这就是为什么第一种溶液更常用[Naftalin07,6.7].

作者scalar type在这里是什么意思,他想在这里传达什么?什么是选项1被认为比选项2更危险?

代码 :

// The elements array will contain only E instances from push(E).
// This is sufficient to ensure type safety, but the runtime
// type of the array won't be E[]; it will always be Object[]!
@SuppressWarnings("unchecked") 
public Stack() {
  elements = (E[]) new Object[DEFAULT_INITIAL_CAPACITY];
}
Run Code Online (Sandbox Code Playgroud)

VS

// Appropriate suppression of unchecked warning
public E pop() {
  if (size == 0)
    throw new EmptyStackException();
  // push requires elements …
Run Code Online (Sandbox Code Playgroud)

java generics effective-java

4
推荐指数
2
解决办法
3444
查看次数

有效的Java Item 9,CaseInsensitiveString示例是否正确?

我正在阅读本书的第二版,第36页.我不了解simmetry问题的解决方案:

@override public boolean equals(Object o) {
    return o instanceof CaseInsensitiveString &&
        ((CaseInsensitiveString) o).s.equalsIgnoreCase(s);
}
Run Code Online (Sandbox Code Playgroud)

如果我有,CaseInsensitiveString cis= new CaseInsensitiveString("hello")并且String s="hello"这种行为是非对称的,因为s.equals(cis) 是真的,但是cis.equals(s) 是假的......

我错过了什么?

java effective-java

4
推荐指数
1
解决办法
258
查看次数

Java - 泛型 - Class"Class <?>"的显式转换和强制转换方法

为什么castClass<?>Class 上使用该方法会在编译时产生未经检查的警告?

如果你偷看了cast方法,你会发现这个代码:

public T cast(Object obj) 
{
    if (obj != null && !isInstance(obj))
        throw new ClassCastException(cannotCastMsg(obj));
    return (T) obj; // you can see there is a generic cast performed here
}
Run Code Online (Sandbox Code Playgroud)

如果我做一个通用演员,编译器抱怨说有unchecked warning.


其他背景资料

你可以找到的我如何到达书有效的Java 2版本中这个问题,第166页(的PDF)的例子.

作者写了这段代码

public <T> T getFavorite(Class<T> type) 
{
    return type.cast(favorites.get(type));
}
Run Code Online (Sandbox Code Playgroud)

VS

public <T> T getFavorite(Class<T> type) 
{
    return (T) (favorites.get(type));
}
Run Code Online (Sandbox Code Playgroud)

我只是没有得到差异,为什么编译器抱怨未经检查的警告.最后,两段代码都做了一个明确的演员(T) object,不是吗?

java generics casting effective-java

4
推荐指数
1
解决办法
1119
查看次数

编写工厂方法最有效的方法是什么?

在大多数情况下,当我们编写工厂方法时,它是一堆if可以继续增长的条件.编写这种方法的最有效方法是什么(if条件最少)?

public A createA(final String id) {
    if (id.equals("A1")) {
      return new A1();
    }
    else if (id.equals("A2")) {
      return new A2();
    }
    return null;
  }
Run Code Online (Sandbox Code Playgroud)

java design-patterns factory factory-pattern effective-java

3
推荐指数
1
解决办法
1539
查看次数

Bloch的Effective Java第2版中常量字段的定义

引用:

如果静态final字段具有可变引用类型,则如果引用的对象是不可变的,则它仍然可以是常量字段.

我不确定这是什么意思; 有人能给出一个例子吗?

java immutability mutability effective-java

3
推荐指数
1
解决办法
101
查看次数

有效的Java项目16(第2版)-转发类是否仅用于允许重用?

我正在经历Effective Java, Item-16 Favor composition over inheritance。我看了Forwarding class下面的例子。

我想知道ForwardingSet上课有什么意义?InstrumentedSet可以很好地实现Set并拥有一个私有实例来调用所有方法。

如果InstrumentedSet将来我们最终拥有更多类似的类,这些类除了基本行为外还需要做一些事情,是否可以促进重用并防止冗余?仅仅是面向未来的设计还是我缺少的其他东西?

// Reusable forwarding class 
public class ForwardingSet<E> implements Set<E> {     
  private final Set<E> s;     
  public ForwardingSet(Set<E> s) { this.s = s; }     
  public void clear()               { s.clear();            }    
  public boolean contains(Object o) { return s.contains(o); }
...
}

// Wrapper class - uses composition in place of inheritance   
public class InstrumentedSet<E> extends ForwardingSet<E> {     
      private int addCount = …
Run Code Online (Sandbox Code Playgroud)

java oop effective-java

3
推荐指数
1
解决办法
193
查看次数

公共方法与公共 API

在干净的代码书中,有一个观点是“公共 API 中的 Javadocs”。

同样,《Effective java》一书也有这样的内容:

“项目 56:为所有公开的 API 元素编写文档注释”。

所以这就是我的问题“所有公共方法都被视为公共 API 吗?”

java code-cleanup effective-java

3
推荐指数
1
解决办法
1564
查看次数

为什么 Java 终结器存在安全问题?

我正在阅读Joshua Bloch 的《Effective Java》。第 8项:避免第 2 章定型剂和清洁剂定型剂和清洁剂中,他指出:

\n
\n

终结器有一个严重的安全问题:它们使您的类容易受到终结器攻击。终结器攻击背后的想法很简单:如果从构造函数或其序列化\nequivalents\xe2\x80\x94中抛出\n异常,则readObjectreadResolve方法(第12)\xe2\x80\x94\n恶意子类的终结器可以在部分构造的\n对象上运行,而该对象应该有\xe2\x80\x9cd。\xe2\x80\x9d 这个终结器可以记录\n对静态字段中的对象,防止其\n被垃圾收集。一旦记录了格式错误的对象,就可以简单地调用该对象上的任意方法,而这些方法本来就不应该被允许存在。从构造函数抛出\n异常应该足以阻止\n对象的存在;在存在终结器的情况下,情况并非如此。\n此类攻击可能会产生可怕的后果。Final 类不会受到终结器攻击,因为没有人可以编写 Final 类的恶意子类。

\n
\n

首先,我知道自 Java 18 以来终结器已被弃用。尽管如此,我认为了解此决定背后的原因很重要。我对上面摘录的理解如下:

\n
    \n
  1. 终结器是不确定的。
  2. \n
  3. 恶意子类可以在部分构造的损坏的超类对象上运行其终结器方法。
  4. \n
  5. 将损坏对象的引用移动到静态字段不会让 JVM 进行垃圾收集。
  6. \n
  7. 攻击者可以使用这个应该在 vine\xe2\x80\x9d 上死掉的对象,并按照他们的意愿行事。因此,存在安全缺陷。
  8. \n
\n

其次,我希望我对这个问题的概念理解是正确的。然而,Bloch 尚未在具体的代码示例中演示这个问题。也许是因为他不想让我们搞乱Object.

\n

您能用代码向我演示一下吗?

\n

例如,如果我有一个超类:

\n
/** Superclass */\npublic class DemoSecurityProblem {\n\n}\n
Run Code Online (Sandbox Code Playgroud)\n

然后通过继承或组合来子类:

\n
public class MaliciousSubClass extends DemoSecurityProblem {\n    DemoSecurityProblem demoSecurityProblem = new DemoSecurityProblem();\n}\n
Run Code Online (Sandbox Code Playgroud)\n

攻击者如何通过终结机制利用这一点?

\n

多谢! …

java garbage-collection memory-management finalizer effective-java

3
推荐指数
1
解决办法
729
查看次数