标签: final

Java中的最终静态变量是否安全?

我已经阅读了很多,但没有找到明确的答案.

我有一个看起来像这样的课程:

    public class Foo() {

        private static final HashMap<String, HashMap> sharedData;

        private final HashMap myRefOfInnerHashMap;

        static {
           // time-consuming initialization of sharedData
           final HashMap<String, String> innerMap = new HashMap<String, String>;
           innerMap.put...
           innerMap.put...
           ...a

           sharedData.put(someKey, java.util.Collections.unmodifiableMap(innerMap));
        }

        public Foo(String key) {
            this.myRefOfInnerHashMap = sharedData.get(key);
        }

        public void doSomethingUseful() {
            // iterate over copy
            for (Map.Entry<String, String> entry : this.myRefOfInnerHashMap.entrySet()) {
                ...
            }
        }
     }
Run Code Online (Sandbox Code Playgroud)

我想知道从Foo实例访问sharedData是否是线程安全的(如构造函数和doSomethingUseful()中所示).Foo的许多实例将在多线程环境中创建.

我的意图是sharedData在静态初始化程序中初始化,之后不再修改(只读).

我读过的是不可变对象本质上是线程安全的.但我只是在实例变量的上下文中看到了这一点.不可变的静态变量是否安全?

我找到的另一个构造是ConcurrentHashMap.我可以创建ConcurrentHashMap类型的sharedData但是它包含的HashMaps也必须是ConcurrentHashMap类型的?基本上..

private static final ConcurrentHashMap<String, HashMap> sharedData;
Run Code Online (Sandbox Code Playgroud)

要么

private static final ConcurrentHashMap<String, ConcurrentHashMap> …
Run Code Online (Sandbox Code Playgroud)

java static multithreading final hashmap

26
推荐指数
5
解决办法
3万
查看次数

双重检查锁定没有挥发性

我看了这个问题,如何做双检锁:

// Double-check idiom for lazy initialization of instance fields
private volatile FieldType field;
FieldType getField() {
    FieldType result = field;
    if (result == null) { // First check (no locking)
        synchronized(this) {
            result = field;
            if (result == null) // Second check (with locking)
                field = result = computeFieldValue();
        }
    }
    return result;
}
Run Code Online (Sandbox Code Playgroud)

我的目标是在没有volatile属性的情况下延迟加载字段(而不是单例).初始化后,字段对象永远不会更改.

经过一些测试我的最终方法:

    private FieldType field;

    FieldType getField() {
        if (field == null) {
            synchronized(this) {
                if (field == null)
                    field = Publisher.publish(computeFieldValue());
            } …
Run Code Online (Sandbox Code Playgroud)

java multithreading final java-memory-model double-checked-locking

26
推荐指数
2
解决办法
7046
查看次数

Java中的final和static

我在一本书中读过这句话,但我不理解:

静态和最终的字段只有一个无法更改的存储空间.

有谁可以帮我解释一下?

java variables static final modifiers

25
推荐指数
2
解决办法
4万
查看次数

打字稿中的最终关键字?

有没有办法让变量可以只分配一次?像这样

interface IFACE{
 a: number;
 final b: number;
}

IFACEConstructor (a: number): IFACE {
 return {a: a, b: 1}
}

test = IFACEConstructor(2);
test.a = 5 //OK
test.b = 2 //Error
Run Code Online (Sandbox Code Playgroud)

final typescript

25
推荐指数
4
解决办法
2万
查看次数

为什么C#不允许在同一行上使用const和static?

为什么C#不允许在同一行上使用const和static?在Java中,您必须将字段声明为"static"和"final"以充当常量.为什么C#不允许你将const声明为final?

我进一步区分在Java中,每个接口都是公共的和抽象的,无论是否显式声明.const本质上不是有效的静态吗?为什么C#对此不以为然?

c# java final const constants

24
推荐指数
3
解决办法
1万
查看次数

静态final int v/s static int

这个问题来自我的Java test学习指南.有人能解释一下为什么会这样吗?

这段代码打印出5号而不是12号.你能解释一下原因吗?你能解释为什么如果第二个变量也是12,它会打印出来final,如果它们都不是,那么它会打印出来final吗?

public class Question26 {
    public static void main(String[] args) {
        System.out.println(Q26.q26.ans);
    }
}

class Q26 {
    public static Q26 q26 = new Q26();
    public int ans;
    private static final int var1 = 5;
    private static int var2 = 7;

    public Q26() {
        ans = var1 + var2;
    }
}
Run Code Online (Sandbox Code Playgroud)

java static final

24
推荐指数
2
解决办法
6028
查看次数

导致这种"可能的精度损失"错误的原因是什么?

我的最终变量有问题.任何帮助将不胜感激.

这是我的第一个工作正常的代码

final int i = 90; 
byte b = i ; 
System.out.println(i);
Run Code Online (Sandbox Code Playgroud)

这是我的第二个代码,它表示可能会损失精度.这有什么不对?

final int i; 
i = 90;
byte b = i ; 
System.out.println(i);
Run Code Online (Sandbox Code Playgroud)

java final

24
推荐指数
1
解决办法
1785
查看次数

有没有办法为Hibernate管理的对象声明最终字段?

我刚刚开始使用Hibernate,到目前为止我看到的所有示例看起来都非常像Hibernate文档中的教程:

package org.hibernate.tutorial.domain;
import java.util.Date;

public class Event {

    private Long id;
    private String title;
    private Date date;

    public Event() {}

    /* Accessor methods... */
}
Run Code Online (Sandbox Code Playgroud)

具体来说:没有任何字段被声明为final,并且必须有一个无参数构造函数,以便Hibernate框架可以实例化该类并设置其字段.

但事情就是这样 - 我真的不喜欢每当我能避免它时就以任何方式使我的类变得可变(Java实践:不可变对象为此做出了相当强烈的论据).那么,即使我要声明每个字段的"最终",有没有办法让Hibernate工作

我知道Hibernate使用Reflection来实例化它的类,因此需要能够调用某种构造函数,而不会冒险选择错误的构造函数或将错误的值传递给它的一个参数,所以它可能更安全调用no-arg构造函数并一次设置一个字段.但是,是否应该可以向Hibernate提供必要的信息,以便它可以安全地实例化不可变对象?

public class Event {

    private final Long id;
    private final String title;
    private final Date date;

    public Event(@SetsProperty("id") Long id,
        @SetsProperty("title") String title,
        @SetsProperty("date") Date date) {

        this.id = id;
        this.title = title;
        this.date = new Date(date.getTime());
    }

    /* Accessor methods... */
} …
Run Code Online (Sandbox Code Playgroud)

java hibernate final pojo

23
推荐指数
3
解决办法
8771
查看次数

一切都是最后的

我一直在使用PMD帮助发现我的Java代码中的潜在问题,我一直在寻找它的建议,分为有用的,特殊的和"WTF ?!".

它一直告诉我要做的事情之一就是将final关键字用于字面上我可以附加的每个变量,包括输入参数.对于实际的常数,这似乎是明智的,但对于其他东西,它只是让我感到奇怪,甚至可能适得其反.

final在每个变量声明上是否有具体的优点/缺点?

java final

23
推荐指数
2
解决办法
3610
查看次数

Java:将所有字段设为final还是volatile?

如果我有一个在线程之间共享的对象,在我看来每个字段应该是final或者volatile,具有以下推理:

  • 如果应该更改字段(指向另一个对象,更新原始值),那么该字段应该是volatile所有其他线程对新值进行操作.仅仅访问所述字段的方法的同步是不够的,因为它们可能返回缓存的值.

  • 如果该领域永远不会改变,那就去做吧final.

但是,我找不到任何关于此的内容,所以我想知道这个逻辑是否有缺陷还是太明显?

当然编辑而不是易失性可能使用final AtomicReference或类似.

编辑,例如,请参阅get getter方法是Java中volatile的替代方法吗?

编辑以避免混淆:这个问题是关于缓存失效!如果两个线程对同一个对象进行操作,则可以缓存对象的字段(每个线程),如果它们未声明为volatile.如何保证缓存无效?

最后的编辑感谢@Peter Lawrey,他指出了JLS§17(Java内存模型).据我所知,它表明同步在操作之间建立了先发生关系,因此如果那些更新"发生在之前",则线程会看到来自另一个线程的更新,例如,如果非易失性字段的getter和setter是synchronized.

java multithreading final volatile

23
推荐指数
2
解决办法
2071
查看次数