Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/400.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/apache-flex/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_Final - Fatal编程技术网

在java中有没有办法将对象的值固定为常量?

在java中有没有办法将对象的值固定为常量?,java,final,Java,Final,我们知道,final关键字创建对对象的常量引用。例如: final Object object = new Object(); 但是,在这种情况下,只有对对象的引用是固定的,并且在程序的执行运行时不能更改。我仍然可以在这个对象上调用setter方法并更改其数据成员的值。有没有一种方法可以在Java(相当于C++中的const)中防止这种情况 我理解这样一种方式,即我不应该为这个对象类定义setter,或者应该只允许设置一次值,但是如果我想将这个对象作为参数传递给一个函数,并且不希望该函数改变这

我们知道,
final
关键字创建对对象的常量引用。例如:

final Object object = new Object();
但是,在这种情况下,只有对对象的引用是固定的,并且在程序的执行运行时不能更改。我仍然可以在这个对象上调用setter方法并更改其数据成员的值。有没有一种方法可以在Java(相当于C++中的const)中防止这种情况

我理解这样一种方式,即我不应该为这个对象类定义setter,或者应该只允许设置一次值,但是如果我想将这个对象作为参数传递给一个函数,并且不希望该函数改变这个对象的数据成员的值,该怎么办呢。我可能仍然希望更改函数外部的值

在这种情况下,功能原型应该是什么

但是,如果我想将这个对象作为参数传递给函数,并且不希望该函数改变这个对象的数据成员的值,该怎么办呢。我可能仍然希望更改函数外部的值

在这种情况下,您应该只将对象的克隆而不是对象本身传递给方法

但是,如果我想将这个对象作为参数传递给函数,并且不希望该函数改变这个对象的数据成员的值,该怎么办呢。我可能仍然希望更改函数外部的值


那么,,您应该只将对象的克隆而不是对象本身传递给该方法。

另一个选项是创建一个委托,该委托覆盖将更改对象状态的所有方法,而不是引发异常或执行禁止操作。

另一个选项是创建一个委托,该委托覆盖将更改对象状态的所有方法更改对象状态,而不是抛出异常或执行禁止操作。

诀窍是定义对象的只读接口,并将setter仅放入类中,如下所示:

public interface ConstInterface {
    int getFirst();
    String getSecond();
}

public class MutableClass implements ConstInterface {
    private int _first;
    private String _second;
    int getFirst() {
        return _first;
    }
    void setFirst(int f) {
        _first = f;
    }
    String getSecond() {
        return _second;
    }
    void setSecond(String s) {
        _second = s;
    }
}

final ConstInterface obj = new MutableClass();

此时,您可以通过其接口以只读方式访问
obj
。如果需要设置属性,请将
obj
强制转换为
MutableClass
,然后调用setter。

技巧是定义对象的只读接口,并将setter仅放入类中,如下所示:

public interface ConstInterface {
    int getFirst();
    String getSecond();
}

public class MutableClass implements ConstInterface {
    private int _first;
    private String _second;
    int getFirst() {
        return _first;
    }
    void setFirst(int f) {
        _first = f;
    }
    String getSecond() {
        return _second;
    }
    void setSecond(String s) {
        _second = s;
    }
}

final ConstInterface obj = new MutableClass();

此时,您可以通过其接口以只读方式访问
obj
。如果需要设置属性,请将
obj
转换为
MutableClass
,然后调用setter。

您有几种解决方案

  • 首先,你可以通过设计来解决它。创建没有可修改对象状态的方法的接口。例如,它将只包含getter。现在变量类型是interface。客户端将无法修改状态
  • 若您的类实现了接口,那个么可以使用动态代理来包装它,以防止调用setter。顺便说一句,如果您的类实际上是collection或map,则可以使用
    Collections.UnmodifiedMap()
    Collections.UnmodifiedReableList()
    使其确实不可修改
  • 您可以使用字节码工程。即使您的类没有实现任何接口,这也会起作用。有两种方法可以做到这一点。javassist和cglib等库允许创建封装具体类的动态代理。因此,您可以使用使用这些库之一创建的代理来包装对象。调用setter时,代理将引发异常
  • 在编译时使用字节码修改。例如,AspectJ可以帮助您

  • 您有几种解决方案

  • 首先,你可以通过设计来解决它。创建没有可修改对象状态的方法的接口。例如,它将只包含getter。现在变量类型是interface。客户端将无法修改状态
  • 若您的类实现了接口,那个么可以使用动态代理来包装它,以防止调用setter。顺便说一句,如果您的类实际上是collection或map,则可以使用
    Collections.UnmodifiedMap()
    Collections.UnmodifiedReableList()
    使其确实不可修改
  • 您可以使用字节码工程。即使您的类没有实现任何接口,这也会起作用。有两种方法可以做到这一点。javassist和cglib等库允许创建封装具体类的动态代理。因此,您可以使用使用这些库之一创建的代理来包装对象。调用setter时,代理将引发异常
  • 在编译时使用字节码修改。例如,AspectJ可以帮助您

  • 为什么不能将字段设置为final?如果字段上有setter,则无法保证字段不会被更改。@DominicBou Samra-如果我将字段设置为final,则只能设置一次值,但我不希望这样。我只是不想在函数的权限范围内更改值。只需在将其传递给函数之前创建一个副本,并将副本传递给函数,那么函数是否更改它就无关紧要了。@AmitD-谢谢您的建议,但在函数级别我可以做些什么吗?我的意思是每次在调用方中创建一个副本,然后传递似乎不是一个好方法。为什么不能将字段设置为final?如果字段上有setter,则无法保证字段不会被更改。@DominicBou Samra-如果我将字段设置为final,则只能设置一次值,但我不希望这样。我只是不想在函数的权限范围内更改值。只需在将其传递给函数之前创建一个副本,并将副本传递给函数,那么函数是否更改它就无关紧要了。@AmitD-谢谢您的建议,但在函数级别我可以做些什么吗?我的意思是每次在调用者中创建一个副本,然后传递似乎不是一个好的方法。@BheshGurung-有没有一种方法可以让我在函数级别做点什么?@AbhishekJain:你有两个选择,要么不改变方法中对象的状态,要么只是传递