Когда мы будем использовать каждый из следующих методов инициализации? [Дубликат]

== сравнивает ссылки на объекты.

.equals() сравнивает значения String.

Иногда == дает иллюзии сравнения значений String, как в следующих случаях:

String a="Test";
String b="Test";
if(a==b) ===> true

Это связано с тем, что при создании любого строкового литерала JVM сначала ищет этот литерал в пуле строк, и если он найдет совпадение, эта же ссылка будет передана новой String. Из-за этого получаем:

(a == b) ===> true

                       String Pool
     b -----------------> "test" <-----------------a

Однако == не выполняется в следующем случае:

String a="test";
String b=new String("test");
if (a==b) ===> false

В этом случае для new String("test") оператор new String будет создан в куче, и эта ссылка будет указана на b, поэтому b будет дана ссылка на кучу, а не на String pool.

Теперь a указывает на String в пуле String, а b указывает на String в куче. Из-за этого мы получаем:

, если (a == b) ===> false.

                String Pool
     "test" <-------------------- a

                   Heap
     "test" <-------------------- b

Пока .equals() всегда сравнивает значение String, поэтому дает true в обоих случаях:

String a="Test";
String b="Test";
if(a.equals(b)) ===> true

String a="test";
String b=new String("test");
if(a.equals(b)) ===> true

Таким образом, использование .equals() всегда лучше.

75
задан Andrew Tobilko 25 November 2017 в 12:16
поделиться

10 ответов

Прежде всего, существуют два типа блоков инициализации :

  • блоков инициализации экземпляра и
  • блоков статической инициализации.

Этот код должен проиллюстрировать их использование и в каком порядке они выполняются:

public class Test {

    static int staticVariable;
    int nonStaticVariable;        

    // Static initialization block:
    // Runs once (when the class is initialized)
    static {
        System.out.println("Static initalization.");
        staticVariable = 5;
    }

    // Instance initialization block:
    // Runs each time you instantiate an object
    {
        System.out.println("Instance initialization.");
        nonStaticVariable = 7;
    }

    public Test() {
        System.out.println("Constructor.");
    }

    public static void main(String[] args) {
        new Test();
        new Test();
    }
}

Отпечатки:

Static initalization.
Instance initialization.
Constructor.
Instance initialization.
Constructor.

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

143
ответ дан aioobe 15 August 2018 в 21:01
поделиться
  • 1
    На данный момент похоже, что они исполняются в порядке появления в коде. Пример может быть улучшен в том, как порядок в коде отличается от фактического порядка выполнения. Также: может быть несколько блоков инициализации, а затем они выполняются в порядке появления (но еще до конструктора). – Thomas Weller 2 December 2014 в 12:39
  • 2
    @Pacerier Итак, вы можете иметь общий код при наличии нескольких конструкторов без использования метода init() (который кто-то, обновляющий класс, может забыть его вызвать) – pablisco 19 August 2016 в 10:28
  • 3
    @Thomas wellerif его выполняет перед конструктором, как он позволяет this ключевое слово inisde instance initialize block. this - объект класса curernt, и он будет полностью построен после завершения вызова конструктора? – amarnath harish 18 June 2018 в 09:59
public class StaticInitializationBlock {

    static int staticVariable;
    int instanceVariable;

    // Static Initialization Block
    static { 
        System.out.println("Static block");
        staticVariable = 5;

    }

    // Instance Initialization Block
    { 

        instanceVariable = 7;
        System.out.println("Instance Block");
        System.out.println(staticVariable);
        System.out.println(instanceVariable);

        staticVariable = 10;
    }


    public StaticInitializationBlock() { 

        System.out.println("Constructor");
    }

    public static void main(String[] args) {
        new StaticInitializationBlock();
        new StaticInitializationBlock();
    }

}

Выход:

Static block
Instance Block
5
7
Constructor
Instance Block
10
7
Constructor
0
ответ дан Anıl Emre Özçelik 15 August 2018 в 21:01
поделиться

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

class Employee { 
 { 
 System.out.println("Employee:initializer"); 
 } 
}
0
ответ дан BERGUIGA Mohamed Amine 15 August 2018 в 21:01
поделиться

хотел бы добавить к ответу @ aioobe

Порядок выполнения:

  1. статические блоки инициализации суперклассов
  2. блоки статической инициализации class
  3. блоки инициализации экземпляров суперклассов
  4. конструкторы суперклассов
  5. блоки инициализации экземпляра класса
  6. конструктора класса.

Несколько дополнительных моментов, которые следует учитывать (пункт 1 - повторение ответа @ aioobe):

  1. Будет выполнен код в статическом блоке инициализации при загрузке класса (и да, это означает только один раз на загрузку класса), прежде чем будут созданы какие-либо экземпляры класса и до вызова каких-либо статических методов.
  2. Блок инициализации экземпляра фактически копируется Java компилятор в каждый конструктор класса. Поэтому каждый раз, когда блок инициализации кода в экземпляре выполняется точно до кода в конструкторе.
79
ответ дан Biman Tripathy 15 August 2018 в 21:01
поделиться
  • 1
    Поэтому, если я создаю 10 экземпляров SomeClass, шаги 1 и 2 выполняются только один раз, пока что-то не вызывает разгрузку класса (единственное, что я могу вспомнить, это перезапустить программу, но если есть другие вещи, которые могут вызвать это, я 'хотел бы знать). – Glen Pierce 20 April 2017 в 01:24
  • 2
    @GlenPierce здесь вы идете: docs.oracle.com/javase/specs/jls/se8/html/jls-12.html#jls-12.7 – Biman Tripathy 20 April 2017 в 18:11

Вопрос не совсем ясен, но вот краткое описание способов инициализации данных в объекте. Предположим, что у вас есть класс A, который содержит список объектов.

1) Поместите начальные значения в объявление поля:

class A {
    private List<Object> data = new ArrayList<Object>();
}

2) Назначьте начальные значения в конструкторе:

class A {
    private List<Object> data;
    public A() {
        data = new ArrayList<Object>();
    }
}

В обоих случаях предполагается, что вы не хотите передавать «данные» в качестве аргумента конструктора.

Все становится немного сложнее, если вы смешиваете перегруженные конструкторы с внутренними данными, такими как выше , Рассмотрим:

class B {
    private List<Object> data;
    private String name;
    private String userFriendlyName;

    public B() {
        data = new ArrayList<Object>();
        name = "Default name";
        userFriendlyName = "Default user friendly name";
    }

    public B(String name) {
        data = new ArrayList<Object>();
        this.name = name;
        userFriendlyName = name;
    }

    public B(String name, String userFriendlyName) {
        data = new ArrayList<Object>();
        this.name = name;
        this.userFriendlyName = userFriendlyName;
    }
}

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

class B {
    private List<Object> data;
    private String name;
    private String userFriendlyName;

    public B() {
        this("Default name", "Default user friendly name");
    }

    public B(String name) {
        this(name, name);
    }

    public B(String name, String userFriendlyName) {
        data = new ArrayList<Object>();
        this.name = name;
        this.userFriendlyName = userFriendlyName;
    }
}

или

class B {
    private List<Object> data;
    private String name;
    private String userFriendlyName;

    public B() {
        init("Default name", "Default user friendly name");
    }

    public B(String name) {
        init(name, name);
    }

    public B(String name, String userFriendlyName) {
        init(name, userFriendlyName);
    }

    private void init(String _name, String _userFriendlyName) {
        data = new ArrayList<Object>();
        this.name = name;
        this.userFriendlyName = userFriendlyName;
    }
}

Эти два (более или меньше).

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

EDIT: Я интерпретировал ваш вопрос как «как инициализировать мои переменные экземпляра», а не «как инициализатор блокирует работу ", поскольку блоки инициализации являются относительно продвинутой концепцией, и из тон вопроса кажется, что вы спрашиваете о более простой концепции. Я мог ошибаться.

0
ответ дан Cameron Skinner 15 August 2018 в 21:01
поделиться

Чтобы узнать, как использовать статический блок инициализации, обратитесь к исходному коду Class.forName также в этой статье http://cephas.net/blog/2005/07/31/java-classfornamestring-classname- и-jdbc / , они используют блок инициализации для загрузки динамического класса.

0
ответ дан Dead Programmer 15 August 2018 в 21:01
поделиться

хороший ответ by aioobe, добавляющий еще несколько точек

public class StaticTest extends parent {
    static {
        System.out.println("inside satic block");
    }

    StaticTest() {
        System.out.println("inside constructor of child");
    }

    {
        System.out.println("inside initialization block");
    }

    public static void main(String[] args) {
        new StaticTest();
        new StaticTest();
        System.out.println("inside main");
    }
}

class parent {
    static {
        System.out.println("inside parent Static block");
    }
    {
        System.out.println("inside parent initialisation block");
    }

    parent() {
        System.out.println("inside parent constructor");
    }
}

, это дает

inside parent Static block
inside satic block
inside parent initialisation block
inside parent constructor
inside initialization block
inside constructor of child
inside parent initialisation block
inside parent constructor
inside initialization block
inside constructor of child
inside main

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

5
ответ дан Gaurav 15 August 2018 в 21:01
поделиться

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

Они обычно используются для инициализации ссылочных переменных. Эта страница дает хорошее объяснение

0
ответ дан Gaurav Saxena 15 August 2018 в 21:01
поделиться
  • 1
    Согласно @Biman, конструкторы из суперклассов запускаются перед блоком init. – Nicolas Barbulesco 7 June 2014 в 21:55
3
ответ дан nenito 15 August 2018 в 21:01
поделиться

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

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

Что делать, если мы хотим выполнить некоторый код один раз для всех объектов класса?

Мы используем Static Block в Java.

1
ответ дан roottraveller 15 August 2018 в 21:01
поделиться
Другие вопросы по тегам:

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