2013-06-20 3 views
9

Я понимаю, что Java-примитивы имеют значения инициализации по умолчанию; например 0 за int.Явная инициализация примитивов

Из моих исследований кажется, что я не должен полагаться на эти ценности. Должен ли я всегда предоставлять явную инициализацию, и если да, то где?

Вот часть моей программы:

public class Calculator { 

// Initialize value where it's declared? 
private int value; 

public Calculator() { 
    // Initialize value in constructor? 
} 

public void add(int other) { 
    value += other; 
} 
} 
+5

«Из моих исследований кажется, что я не должен полагаться на эти ценности» <- uh? Спецификации языка недостаточно для надежного источника для вас? – fge

+2

Речь идет не столько о том, чтобы полагаться на ценности, сколько на то, чтобы сделать его явным для других программистов, какое значение вы используете. –

+0

Если вам не нужно значение по умолчанию, и логически каждый экземпляр вашего класса должен иметь переменные экземпляра, установленные по крайней мере для определенного значения, то для этого вы можете использовать конструктор. – NINCOMPOOP

ответ

4

Использование значений по умолчанию, созданных Java, абсолютно нормально, вам не нужно явно инициализировать поля экземпляра или static вашего class. Спецификация Java Language Specification требует этого, поэтому любая реализация языка должна соответствовать. Другими словами, ваш код останется на 100% переносимым, если вы используете значения по умолчанию для переменных-членов. Это относится как к примитивным, так и к ссылочным типам (позднее они инициализируются null).

См. Java Language Specification, стр. 81, для более подробной информации.

4.12.5 Начальные значения переменных

Каждая переменная в программе должна иметь значение до того, как используется его значение: - Каждая переменная класса, переменная экземпляра, или компонент массива инициализируется со значением по умолчанию при его создании

единственный случай, когда вы должны обеспечить явную инициализацию, когда объявлять локальные переменные:

локальная переменная должна быть явно заданные значения перед его использованием, либо инициализации или назначения, таким образом, что может быть правдой d с использованием правил для определенного назначения.

Однако, поскольку отказ от инициализации локальной является ошибкой времени компиляции, компилятор будет определять каждую пропущенную инициализацию, прежде чем вы сможете запустить свою программу.

0

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

Я думаю, вам нужно будет беспокоиться об этом только в том случае, если вы работаете с каким-то обычным (и бедным) JVM.

1

Из моих исследований кажется, что я не должен полагаться на эти ценности.

Вы можете положиться на них. Не будет никакого вреда, поскольку это делается по умолчанию, как вы уже знаете.

Должен ли я всегда предоставлять явную инициализацию, и если да, то где?

Для примитивов нет необходимости предоставлять явную инициализацию, и я предпочитаю не делать этого. Я редко делаю и вижу, что люди выполняют инициализацию, например, - int i = 0;. Но, если вы говорите о локальных переменных, вам нужно дать им явные значения. По умолчанию они не являются неявными.

Но когда дело доходит для не-примитивов, то вы должны сделать явную инициализацию, либо в точке декларации, или внутри конструктора, так как значения по умолчанию null, что может привести к NPE, если не взят под опеку. Преимущество инициализации в точке объявления заключается в том, что вам не придется ставить инициализацию в каждом из ваших конструкторов.

+1

Вам следует избегать инициализации локальных переменных с помощью переменных по умолчанию или «фиктивных» переменных. Это препятствует статическому анализу, выполняемому компилятором, который может предупредить вас о пропущенном вами пути кода. Например, если вы объявите локальную переменную, а затем прочитаете ее, не присвоив ей значение, компилятор предупредит вас. Если вы инициализировали его бессмысленным значением по умолчанию, компилятор не обнаружит вашу ошибку. Таким образом, оставьте объявления пустыми или подождите, чтобы объявить переменную, пока вы не сможете ее инициализировать с реальным значением. – erickson

+0

@erickson. Да правильно. На самом деле я имел в виду только это. Хорошая практика - объявлять локальные переменные по мере необходимости. это экономит много работы, когда вы застряли в какой-то странной проблеме. –

0

Переменные-члены будут инициализированы значениями по умолчанию. Поэтому вам не о чем беспокоиться. Но если вы хотите инициализировать значениями по умолчанию или другими значениями, вы можете установить их в конструкторе

+0

без конструктора: public class A { public int num = 2; public void A() { } } –

+1

Инициализировать в конструкторе лучше один. – stinepike

+0

это может быть. Я просто предлагаю другой метод –

0

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

Мои личные предпочтения в коде, который вы указали, должны были инициализировать переменную до 0 при объявлении. Это просто потому, что первая операция над переменной равна +=, и мне кажется, что неправильно полагаться на значение по умолчанию для числовых операций. Для этого нет веской причины, так как это будет нормально работать, поскольку это просто неправильно.

0

Вы можете явно доверять первоначальной инициализации JVM значениями по умолчанию.

BTW, явная инициализация будет переведена в байт-код, который бесполезен в этом случае.

Скажет, у вас есть этот класс:

public class PrimitiveInitialization { 
    int i = 0; 
    int j; 
} 

корреспондент байткод будет

class PrimitiveInitialization { 
    I i 
    I j 

    public <init>()V 
    L0 
    LINENUMBER 8 L0 
    ALOAD 0 
    INVOKESPECIAL java/lang/Object.<init>()V 
    L1 
    LINENUMBER 10 L1 
    ALOAD 0 
    ICONST_0 
    PUTFIELD PrimitiveInitialization.i : I 
    RETURN 
    L2 
    LOCALVARIABLE this LPrimitiveInitialization; L0 L2 0 
    MAXSTACK = 2 
    MAXLOCALS = 1 
} 

Мы можем видеть, что явная инициализация добавляет несколько операций байткода для переменной i.

Сказанное, вы всегда должны предпочесть читаемость кода, так как JIT, вероятно, может оптимизировать этот тип байт-кода во время выполнения.

0

Значения по умолчанию надежны.

На самом деле они «более» надежны, чем явное обнуление, потому что назначаются по умолчанию - перед всеми другими действиями.