因此,我们创建了一个包含一些私有类成员的简单类,并自动为其生成getter。但getter实际上返回了对该成员的引用,从而获得了对私有成员的完全访问权。这样可以吗?下面是一个类的代码:
public class User {
private ArrayList<String> strings = new ArrayList(){ {
add("String1");
add("String2");
} };
public User() {
}
public ArrayList<String> getStrings() {
return strings;
}
public void setStrings(ArrayList<String> strings) {
this.strings = strings;
}
}
主要方法代码:
public class Main {
public static void main(String[] args){
User user = new User();
System.out.println(user.getStrings());
user.getStrings().add("String3");
System.out.println(user.getStrings());
}
}
和输出:
[字符串1,字符串2]
[字符串1、字符串2、字符串3]
我已经将getter更改为这个:
public ArrayList<String> getStrings() {
return (ArrayList<String>)strings.clone();
}
但问题仍然是,如果不是为了安全,吸气剂的作用是什么?什么是正确的书写方式?
在我看来,getter通常应该有两个目的:
如果您的示例违反了这些原则,则取决于上下文:
不,这不好,因为它破坏了封装,因此类无法维护自己的不变量。与施工人员相同。
但问题不在于getter/setter,而是自动生成它们的代码。
长话短说:不要盲目使用自动生成的访问器,如果它们处理的是可变结构,那么就制作防御性拷贝(或不可变的等价物)。
顺便说一句,我不会使用带有返回类型的数组列表的getter,即使它只是一个副本。您返回什么样的列表通常与客户无关,因此我的getter如下所示:
public List<String> getStrings() {
return new ArrayList<>(strings);
}
或使用不可变视图:
public List<String> getStrings() {
return Collections.unmodifiableList(strings);
}
或者使用Guava的ImMutableList
类:
public List<String> getStrings() {
return ImmutableList.copyOf(strings);
}
这三种解决方案之间存在细微的差异,因此哪一种最好可能会有所不同。一般来说,我更喜欢返回不可变的结构,因为这清楚地表明,对结构所做的更改不会被反映出来,即,<代码>用户。getStrings()。添加(“X”) 将失败并出现异常。
您向我们展示的代码的另一个微妙问题是双大括号的初始化。想象这样一个类:
public class Foo {
private List<String> strings = new ArrayList() {{ add("bar");}};
private Object veryLargeField; //the object stored here consumes a lot of memory
public List<String> getStrings() {
return strings;
}
}
现在想象一下我们正在这样做:
private class Bar {
private List<String> fooStrings;
public Bar() {
this.fooStrings = new Foo().getStrings();
}
}
Bar
会消耗多少内存(或者使用准确的术语:保留)?好吧,事实证明这相当多,因为您使用双括号初始化所做的是创建一个匿名内部类,它将包含对其外部类(Foo
)的引用,因此当返回的列表可访问时,Foo
的所有其他字段都将不符合垃圾回收机制的条件。
编译器为自动为所有的public的状态变量创建访问函数。下面的合约例子中,编译器会生成一个名叫data的无参,返回值是uint的类型的值data。状态变量的初始化可以在定义时完成。 pragma solidity ^0.4.0; contract C{ uint public c = 10; } contract D{ C c = new C(); functi
考虑java中的此类(数据不是私有的或公共的): 我将这个类转换为kotlin 反编译后的代码是这样的: 在kotlin类中,dataPart2调用数据getter(检查反编译代码中的第2行),但我需要访问数据的实际值而不是getter,在kotlin中是否可以访问字段而不调用getter?我不想更改getter或方法名称。
我有一个应用程序,它有一个ConcurrentHashMap本地存储一个存储在外部服务器上的数据副本。地图每隔几秒钟就会更新一次数据的新副本。 我有一个循环,每隔几秒钟运行一次,它可以访问HashMap并按照值的顺序将元素添加到数组中(实际上它做的事情还多一些,但这并不相关)。我的问题是,如果数据在创建数组的过程中发生了变化,您可能会在不同的地方有重复的键,或者完全省略一些键。 示例: 如您所见,
我正在用Java RMI编写一个客户机-服务器程序,但遇到了一个错误: java.security.访问控制异常:拒绝访问(java.net.SocketPersion127.0.0.1:1099连接,解析) 我的代码如下: 怎么了?
我已经创建了谷歌应用程序引擎项目,使用预测Api 1.5v。当我在本地均值localhost:8888使用谷歌o2Auth身份验证与客户端ID和客户端运行时,它对我来说工作正常secret.but当我实时运行它时,它会给出一个错误 Java语言安全AccessControlException:访问被拒绝(“java.io.FilePermission”“/base/data/home/apps/s
我的Quarkus申请一直面临一个问题。该应用程序在本地开发模式下运行时可以正常工作,但是当它作为本地映像构建时,我面临一些奇怪的问题。 遇到的错误: 访问私有intjava.util.ArrayList.size的偏移量时,不首先将字段注册为不安全访问。 org.hibernate.type.serializationexception不能反序列化 java.io.InvalidClassExc