Изменение заключительных полей в Java

Первый вопрос - знакомы ли вы с лямбда-выражениями в C #? Если это так, то -> в F # совпадает с => в C # (я думаю, что вы читаете, он «идет»).

Оператор -> также можно найти в контексте сопоставления с образцом

match x with
| 1 -> dosomething
| _ -> dosomethingelse

Я не уверен, является ли это лямбда-выражением, или что-то еще, но я предполагаю, что 'идет к 'все еще держит.

Возможно, вы действительно имеете в виду «загадочные» ответы синтаксического анализатора F #:

> let add a b = a + b
val add: int -> int -> int

Это означает (как объясняет большинство примеров), что add - это «val», который занимает два целых и возвращает int. Для меня это было совершенно непрозрачно с самого начала. Я имею в виду, откуда мне знать, что add - это не val, который принимает одно целое и возвращает два целых?

Ну, в некотором смысле это так. Если я добавлю только один int, я получу обратно (int -> int):

> let inc = add 1
val inc: int -> int

Это (карри) - одна из вещей, которая делает F # такой сексуальной для меня.

Для полезной информации о F # я обнаружил, что блоги на FAR более полезны, чем любая официальная «документация»: вот некоторые имена, которые нужно проверить

51
задан ChssPly76 23 October 2009 в 07:28
поделиться

3 ответа

Константы времени компиляции встроены (во время компиляции javac). См. JLS, в частности, 15.28 определяет постоянное выражение, а 13.4.9 обсуждает двоичную совместимость или конечные поля и константы.

Если вы сделаете поле неокончательным или назначаете временную константу, не являющуюся компиляцией, значение не будет встроено. Например:

private final String stringValue = null! = Null? "": "42";

21
ответ дан 7 November 2019 в 10:24
поделиться

Это не ответ, но он вызывает еще одну путаницу:

Я хотел увидеть, была ли проблема в оценке времени компиляции или действительно ли отражение позволяло Java получить вокруг ключевого слова final . Вот тестовая программа. Все, что я добавил, это еще один набор вызовов геттера, так что есть один до и после каждого вызова changeField () .

package com.example.gotchas;

import java.lang.reflect.Field;

public class MostlyFinal {
  private final int primitiveInt = 42;
  private final Integer wrappedInt = 42;
  private final String stringValue = "42";

  public int getPrimitiveInt()   { return this.primitiveInt; }
  public int getWrappedInt()     { return this.wrappedInt; }
  public String getStringValue() { return this.stringValue; }

  public void changeField(String name, Object value) throws IllegalAccessException, NoSuchFieldException {
    Field field = MostlyFinal.class.getDeclaredField(name);
    field.setAccessible(true);
    field.set(this, value);
    System.out.println("reflection: " + name + " = " + field.get(this));
  }

  public static void main(String[] args) throws IllegalAccessException, NoSuchFieldException {
    MostlyFinal test = new MostlyFinal();

    System.out.println("direct: primitiveInt = " + test.getPrimitiveInt());
    test.changeField("primitiveInt", 84);
    System.out.println("direct: primitiveInt = " + test.getPrimitiveInt());

    System.out.println();

    System.out.println("direct: wrappedInt = " + test.getWrappedInt());
    test.changeField("wrappedInt", 84);
    System.out.println("direct: wrappedInt = " + test.getWrappedInt());

    System.out.println();

    System.out.println("direct: stringValue = " + test.getStringValue());
    test.changeField("stringValue", "84");
    System.out.println("direct: stringValue = " + test.getStringValue());
  }
}

Вот результат, который я получаю (в Eclipse, Java 1.6)

direct: primitiveInt = 42
reflection: primitiveInt = 84
direct: primitiveInt = 42

direct: wrappedInt = 42
reflection: wrappedInt = 84
direct: wrappedInt = 84

direct: stringValue = 42
reflection: stringValue = 84
direct: stringValue = 42

Какого черта прямой вызов getWrappedInt () изменить?

1
ответ дан 7 November 2019 в 10:24
поделиться

SET SET (. .) Метод работает с Fieldaccessor s.

Для INT INT получает UnsafequavavelifyInteGrefiledAccessorImpl , чьи суперкласс определяет свойство Readly , чтобы быть правдой только в том случае, если поле как и Финал

Итак, чтобы сначала ответить на незаменимый вопрос - вот почему финал изменяется без исключения.

Все подклассы UnsafequeFifyFieldAccessor используют класс Sun.misc.unsafe , чтобы получить значения. Способы есть все родные , но их имена getVolatileint (..) и GetInt (..) ( getVolatileObject (..) и GetObject (..) соответственно). Вышеупомянутые доступа используют «волатильную» версию. Вот что произойдет, если мы добавим ненутрительную версию:

System.out.println("reflection: non-volatile primitiveInt = "
     unsafe.getInt(test, (long) unsafe.fieldOffset(getField("primitiveInt"))));

(где небезопасно создается по отражению - это не допускается иначе) (И я звоню GetObject для целого числа и и )

, что дает некоторые интересные результаты:

reflection: primitiveInt = 84
direct: primitiveInt = 42
reflection: non-volatile primitiveInt = 84
reflection: wrappedInt = 84
direct: wrappedInt = 84
reflection: non-volatile wrappedInt = 84
reflection: stringValue = 84
direct: stringValue = 42
reflection: non-volatile stringValue = 84

на данный момент я вспоминаю статью На javaspecialists.eu обсуждает связанный счет. Это цитирует jsr-133 :

Если окончательное поле инициализируется для постоянной времени компиляции в полевой декларации, изменения в последнее время не наблюдаются, поскольку использование этого окончательного поля заменяется При компиляции время с постоянной времени компиляции.

Глава 9 обсуждает детали, наблюдаемые в этом вопросе.

И оказывается, что это поведение не в том, что неожиданно, поскольку модификации поля финала должны произойти только сразу после инициализации объекта.

7
ответ дан 7 November 2019 в 10:24
поделиться
Другие вопросы по тегам:

Похожие вопросы: