我正在尝试按照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) 我读了Effective Java,并写了
如果一个类不能成为不可变的,尽可能地限制它的可变性......
和
......除非有令人信服的理由使其成为非最终的,否则每个领域都是最终的.
所以需要我总是让我所有的POJO(例如简单的Book带班ID,Title和Author域)班不变?当我想要改变我的对象的状态时(例如用户在代表很多书的表中更改它),而不是setter使用这样的方法:
public Book changeAuthor(String author) {
return new Book(this.id, this.title, author); //Book constructor is private
}
Run Code Online (Sandbox Code Playgroud)
但我的事情真的不是好主意..
请解释我何时使类不可变.
来自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) 我正在阅读本书的第二版,第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)
是假的......
我错过了什么?
为什么cast在Class<?>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,不是吗?
在大多数情况下,当我们编写工厂方法时,它是一堆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) 引用:
如果静态final字段具有可变引用类型,则如果引用的对象是不可变的,则它仍然可以是常量字段.
我不确定这是什么意思; 有人能给出一个例子吗?
我正在经历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) 在干净的代码书中,有一个观点是“公共 API 中的 Javadocs”。
同样,《Effective java》一书也有这样的内容:
“项目 56:为所有公开的 API 元素编写文档注释”。
所以这就是我的问题“所有公共方法都被视为公共 API 吗?”
我正在阅读Joshua Bloch 的《Effective Java》。第 8项:避免第 2 章的定型剂和清洁剂定型剂和清洁剂中,他指出:
\n\n\n终结器有一个严重的安全问题:它们使您的类容易受到终结器攻击。终结器攻击背后的想法很简单:如果从构造函数或其序列化\nequivalents\xe2\x80\x94中抛出\n异常,则
\nreadObject和readResolve方法(第12)\xe2\x80\x94\n恶意子类的终结器可以在部分构造的\n对象上运行,而该对象应该有\xe2\x80\x9cd。\xe2\x80\x9d 这个终结器可以记录\n对静态字段中的对象,防止其\n被垃圾收集。一旦记录了格式错误的对象,就可以简单地调用该对象上的任意方法,而这些方法本来就不应该被允许存在。从构造函数抛出\n异常应该足以阻止\n对象的存在;在存在终结器的情况下,情况并非如此。\n此类攻击可能会产生可怕的后果。Final 类不会受到终结器攻击,因为没有人可以编写 Final 类的恶意子类。
首先,我知道自 Java 18 以来终结器已被弃用。尽管如此,我认为了解此决定背后的原因很重要。我对上面摘录的理解如下:
\n其次,我希望我对这个问题的概念理解是正确的。然而,Bloch 尚未在具体的代码示例中演示这个问题。也许是因为他不想让我们搞乱Object.
您能用代码向我演示一下吗?
\n例如,如果我有一个超类:
\n/** Superclass */\npublic class DemoSecurityProblem {\n\n}\nRun Code Online (Sandbox Code Playgroud)\n然后通过继承或组合来子类:
\npublic class MaliciousSubClass extends DemoSecurityProblem {\n DemoSecurityProblem demoSecurityProblem = new DemoSecurityProblem();\n}\nRun Code Online (Sandbox Code Playgroud)\n攻击者如何通过终结机制利用这一点?
\n多谢! …
java garbage-collection memory-management finalizer effective-java
effective-java ×10
java ×10
immutability ×3
generics ×2
casting ×1
code-cleanup ×1
factory ×1
finalizer ×1
mutability ×1
oop ×1