【问题标题】:"CONST" in javajava中的“常量”
【发布时间】:2011-06-30 10:31:05
【问题描述】:

我对 java 中的“CONST”有疑问。

我想知道如何用 C 语言制作类似“const struct VAL &getVal()”。

这里是示例代码。

public class test {
   /* VAL is just structure-like class */
   class VAL {
    public int i;
   };
   private VAL  val;

   /* test class functions */
   test() {
    val = new VAL();
    val.i = 1;
   }

   VAL getVal() {
    return val;
   }

   /* main function */
   public static void main(String[] args) {
    test t = new test();
    VAL  t_val;

    t_val = t.getVal();

    t_val.i = 2; /* it should be error if t_val variable is a const */
    System.out.printf("%d %d\n", t.getVal().i, t_val.i);
   }
}

以下是 C 示例代码。

struct VAL
{
    int i;
};

const struct VAL &getVal() /* THIS IS WHAT I WANT */
{
    static VAL xxx;
    return xxx;
}

int main()
{
    const VAL &val = getVal();
    val.i = 0; /* error */

    VAL val2 = getVal();
    val2.i = 0; /* it's not an error, but it's ok because it cannot be changed xxx variable in getVal() either. */

    return 0;
}

【问题讨论】:

  • 为什么你需要这个结构是不可变的?如果问题在于它与不应在外部更改的数据结构有关,那么您可能会返回结构的副本而不是结构本身,因此返回结构的更改不会影响主数据结构。

标签: java


【解决方案1】:

final 关键字具有相似的语义。您不能更改对象的引用,但是如果对象是可变的,您可以更改对象本身。我建议谷歌它并阅读更多关于它的信息。

【讨论】:

  • 我不想更改返回变量。我想阻止更改返回值。
  • @kellinggun 你的意思是对象引用还是原始值。在对象引用的情况下,我看到的唯一方法是使此类不可变。将所有字段和设置方法设为私有。这样你就可以确定没有人可以改变它。如果您指的是原始值,它们总是按值传递。
  • 'final 关键字具有相似的语义':不,它没有。 Java 中没有 C++ 引用之类的东西,'final' 与 'const &' 具有不同的语义。答案错误。
  • @EJP 相似但不完全相同。如果在原语上使用final,它的效果与 const 相同。我又错了吗?
  • 真的很不一样。 'const' 影响调用序列签名; “最终”没有。 'const' 可以与 Java 中不存在的 '&' 一起使用。相似之处少于不同之处。
【解决方案2】:

你不能像在 C 中那样做完全相同的事情。即使你使用final 关键字,它也只会阻止变量引用的修改。如果将 i 声明为最终属性,t_val.i = 2 将出错。

【讨论】:

    【解决方案3】:

    将 VAL 的成员变量设为私有,并提供公共 getter。如果您仍然希望其他人能够在初始化后更改成员,则可以使用仅具有 getter 的接口,以及具有公共 setter 的实现类。然后,返回类的接口,这样调用者就不能改变它的成员了。

    interface ValGetters {
       public int getI();
    }
    
    class Val implements ValGetters {
       private int i;
       public int getI() { return i; }
       public void setI(int ii) { i = ii; }
    }
    

    在内部,持有一个 Val。当您想让其他人使用它时,请以 ValGetters 的身份返回。

    【讨论】:

    • 我对你的回答还有一个问题。
    • 我可以尝试从 ValGetter 对象到 Val 对象的类型转换吗?像这样“Val val = (Val) valgetter;”
    • @killinggun 是的,你可以这样做。但如果您担心有人试图破解您的代码,您可以将class Val 设为私有,将interface ValGetters 设为公开。这样,假设 Val 是嵌套的,您只能在嵌套类中使用 Val(您也可以将其设为常规类,但不是公共类,因此只能从包中访问它)。但无论如何,OOP 是关于合同的。如果有人将其转换回 Val,然后您将 ValGetters 的实现类更改为 Val2,他的代码将在运行时崩溃。
    【解决方案4】:

    const struct VAL &getVal() /* 这是 我想要什么*/

    在 Java 中没有这样的结构,尽管所有答案都相反,尤其是那些暗示“final”关键字的答案。

    【讨论】:

      【解决方案5】:

      更好的方法是使用枚举。他们非常强大。 您可以在 switch 语句中使用它,并且可以根据需要使用 struct 具有内部属性。 您可以在http://download.oracle.com/javase/tutorial/java/javaOO/enum.html 查找文档。

      【讨论】:

      • 该代码只是一个简单的版本。真正的代码比它更复杂。
      • 我真正想要的是函数返回的 CONST-STRUCT_VARIABLE。
      • 你可以用枚举来实现它,就像你写的那样。这些是有点复杂的枚举。
      【解决方案6】:

      简短的回答是你不能,至少不是一般意义上的。如果你使用所有原语(或你创建的都是原语的类)和极少数的类(想到字符串),你可以,但你不能在一般意义上这样做,因为你无法控制人们做什么在调用 getter 方法后使用您的对象。如果你想这样做,你有两个选择:

      1. 将你所有的 FIELDS(不是你的班级,你的 FIELDS,在本例中为 i)设为 final,这样人们就无法更改它们。

      2. 将所有字段设为私有,不要创建任何公共设置器(这是首选方法)

      但是,回到我原来的观点:

      假设 val 是这样定义的:

      public class VAL {
              private List<Integer> i=new ArrayList<Integer>();
              public VAL() {
                  i.add(3);
               }
              public List<Integer> getI() {return i;}
             };
      

      现在没有人可以更改列表指向的对象,但是他们可以很好地更改 i 指向的对象,但是这样的代码是完全有效的(即使 i 被标记为 final 也是有效的):

      VAL bob=new VAL();
      System.out.println(bob.getI().size());
      bob.getI().clear();
      System.out.println(bob.getI().size());
      

      上面的代码会打印出来 1 0

      意思是虽然我没变,但是你的列表内容变了......

      【讨论】:

        【解决方案7】:

        使用final 关键字。这是const的模拟

        【讨论】:

        猜你喜欢
        • 2016-04-21
        • 1970-01-01
        • 2021-10-21
        • 2013-09-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-07-05
        相关资源
        最近更新 更多