如何在Java中创建常量对象?

如何在Java中创建常量对象?,java,Java,如何创建对常量对象的引用 final Myclass obj = new Myclass(); 不起作用,它说obj(参考)不应该被重新分配,但我们仍然可以更改参考的对象我想确保对象本身在构建后不会发生更改。是的,您似乎忘记设置类型了 final MyClass obj = new Myclass(); 这意味着obj只能分配一次。java没有C++类的const关键字。如果MyClass没有声明为final(final class MyClass{…}),它仍然可以更改。只需使其不可变(如

如何创建对常量对象的引用

final Myclass obj = new Myclass();

不起作用,它说obj(参考)不应该被重新分配,但我们仍然可以更改参考的对象

我想确保对象本身在构建后不会发生更改。

是的,您似乎忘记设置类型了

final MyClass obj = new Myclass();

这意味着obj只能分配一次。java没有C++类的const关键字。如果MyClass没有声明为final(final class MyClass{…}),它仍然可以更改。

只需使其不可变(如
String
is)。或者将其包装在另一个对象中,以限制对所讨论对象的变体的访问(就像和配偶一样)。

最终变量应在声明时指定

final MyClass obj = new MyClass();

我认为Java中没有任何内置关键字可以实现这一点。即使引用是常量/最终的,对象的内部仍然可以更改

最好的选择是拥有类的只读实现版本


您可以在此处阅读更多信息:

您需要的是一个。Java中没有任何关键字可以立即使对象不可变。您必须设计对象的逻辑,使其状态无法更改。正如BalusC所说,您可以将其包装到另一个对象中,从而限制对其变体的访问。

在java对象常量中,意味着您不能更改其引用,但可以更改其状态变量的值,直到它们不是最终值为止。如果所有的成员变量都是final,那么它就是一个完美的常量,在这里你不能改变任何东西。

你混合了两个东西:final和immutable

变量可以是final,因此初始化后不能更改它的值(或对象引用)(当然可以更改引用的对象属性)


对象可以是不可变的(不是关键字而是属性),因此在创建后不能更改其值。字符串就是一个很好的例子-您不能更改字符串对象内的backing char[]。

在Java中,不可变类通常意味着它没有“setter”,任何可以使用“getter”访问的字段也应该是不可变的。为了让数据进入类以启动,您需要有一个将值作为参数的构造函数:

public class MyClass { String something; int somethingElse; // The class can only be modified by the constructor public MyClass(String something, int somethingElse) { this.something = something; this.somethingElse = somethingElse; } // Access "something". Note that it is a String, which is immutable. public String getSomething() { return something; } // Access "somethingElse". Note that it is an int, which is immutable. public int getSomethingElse() { return somethingElse; } } 公共类MyClass{ 串东西; intsomethingelse; //该类只能由构造函数修改 公共MyClass(字符串something,int somethingElse){ 这个,某物,某物; this.somethingElse=somethingElse; } //访问“something”。请注意,它是一个不可变的字符串。 公共字符串getSomething(){ 归还某物; } //访问“somethingElse”。注意,它是一个int,是不可变的。 public int getSomethingElse(){ 回报一些东西; } }
下面是一种包装任何对象以使其“大致”不可变的方法

所有不是“getter”的方法调用都将抛出异常。此代码将getter定义为满足以下条件的方法:

  • 方法的名称以
    get
    is
    开头
  • 这不需要争论
  • 它返回一个值(不是
    void
    返回类型)
是的,getter方法可以改变对象。但是,如果您的代码(或您正在使用的代码)正在这样做,您会遇到一些更大的问题,请去寻求帮助:)

守则:

class ImmutableWrapper
    public static <T> T wrap(T thing) {
        return (T) Proxy.newProxyInstance(thing.getClass().getClassLoader(), new Class[]{thing.getClass()}, OnlyGettersInvocationHandler.instance);
    }

    private static class OnlyGettersInvocationHandler implements InvocationHandler {
        public static InvocationHandler instance;
        @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            final String name = method.getName();
            if ((args == null || args.length == 0)
                    && (name.startsWith("get") || name.startsWith("is")
                    && !method.getReturnType().equals(Void.class))) {
                return method.invoke(proxy, args);
            } else {
                throw new UnsupportedOperationException("immutable object: " + proxy + ", cannot call " + name);
            }
        }
    }
}

SomeClass myThing = ... create and populate some object ...
SomeClass myImmutableThing = ImmutableWrapper.wrap(myThing);
myImmutableThing.setValue('foo');   // throws Exception
myImmutableThing.whatever();        // throws Exception
myImmutableThing.getSomething();    // returns something
myImmutableThing.isHappy();         // returns something
类ImmutableWrapper
公共静态T形包装(T形){
返回(T)Proxy.newProxyInstance(thing.getClass().getClassLoader(),新类[]{thing.getClass()},OnlyGettersInvocationHandler.instance);
}
私有静态类OnlyGettersInvocationHandler实现InvocationHandler{
公共静态调用处理程序实例;
@重写公共对象调用(对象代理、方法、对象[]args)抛出可丢弃的{
最终字符串名=method.getName();
if((args==null | | args.length==0)
&&(name.startsWith(“get”)| name.startsWith(“is”)
&&!method.getReturnType().equals(Void.class))){
返回方法.invoke(代理,参数);
}否则{
抛出新的UnsupportedOperationException(“不可变对象:“+proxy+”,不能调用“+name”);
}
}
}
}
SomeClass神话=。。。创建并填充一些对象。。。
SomeClass myImmutableThing=ImmutableWrapper.wrap(虚构);
myImmutableThing.setValue('foo');//抛出异常
myImmutableThing.whatever();//抛出异常
myImmutableThing.getSomething();//归还某物
myImmutableThing.isHappy();//归还某物

也许您可以创建带有最终属性的类。所以,您不能更改它:object==const

至少“String”是不可变的,因为它:

public final class String implements Serializable, Comparable<String>, CharSequence {
    private final char[] value; 
//...
}
public final类字符串实现可序列化、可比较的字符序列{
私有最终字符[]值;
//...
}

如果您的对象对外部类是不可变的(没有设置器,只有私有成员),并且您不更改对象类本身内部的状态,这是可能的。是的,这就是我对只读实现的意思。只让访问内部但不允许更改它们的公共函数。对,但这在Java中仍然是可能的:)。重新表述了回复的第一部分。不可能的话,我的意思是,没有关键字会给它的行为,例如在C++中。现在全部修复。您如何确切地更改引用的对象?您是否正在设置obj的值?或者您正在更改obj中的值?Java不应允许您更改obj指向的内容。这就是最后一个变量的含义。要处理使obj的内容不可变的问题,您需要编写一个不可变类,如下所述。但是,是否存在讨论的链接