Первый вопрос - знакомы ли вы с лямбда-выражениями в 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 более полезны, чем любая официальная «документация»: вот некоторые имена, которые нужно проверить
Константы времени компиляции встроены (во время компиляции javac). См. JLS, в частности, 15.28 определяет постоянное выражение, а 13.4.9 обсуждает двоичную совместимость или конечные поля и константы.
Если вы сделаете поле неокончательным или назначаете временную константу, не являющуюся компиляцией, значение не будет встроено. Например:
private final String stringValue = null! = Null? "": "42";
Это не ответ, но он вызывает еще одну путаницу:
Я хотел увидеть, была ли проблема в оценке времени компиляции или действительно ли отражение позволяло 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 () изменить?
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 обсуждает детали, наблюдаемые в этом вопросе.
И оказывается, что это поведение не в том, что неожиданно, поскольку модификации поля финала
должны произойти только сразу после инициализации объекта.