Рубрики
Без рубрики

Установите значение поля с отражением

Узнайте, как установить значения частных полей на Java с помощью API Reflection.

Автор оригинала: baeldung.

1. Обзор

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

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

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

2. Установка примитивных полей

Мы можем установить поля, которые являются примитивами, используя Полевой наборXxx методы .

2.1. Установка полей интеграторов

Мы можем использовать setByte, наборШорт , s etInt , и setLong методы настройки byte , короткие , int , и долго полей, соответственно:

@Test
public void whenSetIntegerFields_thenSuccess() 
  throws Exception {
    Person person = new Person();

    Field ageField = person.getClass()
        .getDeclaredField("age");
    ageField.setAccessible(true);

    byte age = 26;
    ageField.setByte(person, age);
    Assertions.assertEquals(age, person.getAge());

    Field uidNumberField = person.getClass()
        .getDeclaredField("uidNumber");
    uidNumberField.setAccessible(true);

    short uidNumber = 5555;
    uidNumberField.setShort(person, uidNumber);
    Assertions.assertEquals(uidNumber, person.getUidNumber());

    Field pinCodeField = person.getClass()
        .getDeclaredField("pinCode");
    pinCodeField.setAccessible(true);

    int pinCode = 411057;
    pinCodeField.setInt(person, pinCode);
    Assertions.assertEquals(pinCode, person.getPinCode());

    Field contactNumberField = person.getClass()
        .getDeclaredField("contactNumber");
    contactNumberField.setAccessible(true);

    long contactNumber = 123456789L;
    contactNumberField.setLong(person, contactNumber);
    Assertions.assertEquals(contactNumber, person.getContactNumber());

}

Кроме того, можно выполнить Распаковки с примитивными типами:

@Test
public void whenDoUnboxing_thenSuccess() 
  throws Exception {
    Person person = new Person();

    Field pinCodeField = person.getClass()
        .getDeclaredField("pinCode");
    pinCodeField.setAccessible(true);

    Integer pinCode = 411057;
    pinCodeField.setInt(person, pinCode);
    Assertions.assertEquals(pinCode, person.getPinCode());
}

S etXxx методы для примитивных типов данных также поддерживают сужение :

@Test
public void whenDoNarrowing_thenSuccess() 
  throws Exception {
    Person person = new Person();

    Field pinCodeField = person.getClass()
        .getDeclaredField("pinCode");
    pinCodeField.setAccessible(true);

    short pinCode = 4110;
    pinCodeField.setInt(person, pinCode);
    Assertions.assertEquals(pinCode, person.getPinCode());
}

2.2. Установка плавучих полей типа

Установить поплавок и двойной поля, мы должны использовать установитьFloat и наборДабл методы, соответственно:

@Test
public void whenSetFloatingTypeFields_thenSuccess() 
  throws Exception {
    Person person = new Person();

    Field heightField = person.getClass()
        .getDeclaredField("height");
    heightField.setAccessible(true);

    float height = 6.1242f;
    heightField.setFloat(person, height);
    Assertions.assertEquals(height, person.getHeight());

    Field weightField = person.getClass()
        .getDeclaredField("weight");
    weightField.setAccessible(true);

    double weight = 75.2564;
    weightField.setDouble(person, weight);
    Assertions.assertEquals(weight, person.getWeight());
}

2.3. Установка полей персонажей

Установить char поля, мы можем использовать setChar метод:

@Test
public void whenSetCharacterFields_thenSuccess() 
  throws Exception {
    Person person = new Person();

    Field genderField = person.getClass()
        .getDeclaredField("gender");
    genderField.setAccessible(true);

    char gender = 'M';
    genderField.setChar(person, gender);
    Assertions.assertEquals(gender, person.getGender());
}

2.4. Установка булеанских полей

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

@Test
public void whenSetBooleanFields_thenSuccess() 
  throws Exception {
    Person person = new Person();

    Field activeField = person.getClass()
        .getDeclaredField("active");
    activeField.setAccessible(true);

    activeField.setBoolean(person, true);
    Assertions.assertTrue(person.isActive());
}

3. Установка полей, которые являются объектами

Мы можем установить поля, которые являются объектами с помощью Полевой набор метод :

@Test
public void whenSetObjectFields_thenSuccess() 
  throws Exception {
    Person person = new Person();

    Field nameField = person.getClass()
        .getDeclaredField("name");
    nameField.setAccessible(true);

    String name = "Umang Budhwar";
    nameField.set(person, name);
    Assertions.assertEquals(name, person.getName());
}

4. Исключения

Теперь давайте обсудим исключения, которые JVM может бросить при настройке полей.

4.1. НезаконноеаргументЭксцепция

СПМ бросит НезаконныеАргументЭксцепция если мы используем setXxx мутатор, несовместимый с типом цели . В нашем примере, если мы пишем nameField.setInt (человек, 26) , JVM бросает это исключение, так как поле имеет тип Струнные а не int или Интегер :

@Test
public void givenInt_whenSetStringField_thenIllegalArgumentException() 
  throws Exception {
    Person person = new Person();
    Field nameField = person.getClass()
        .getDeclaredField("name");
    nameField.setAccessible(true);

    Assertions.assertThrows(IllegalArgumentException.class, () -> nameField.setInt(person, 26));
}

Как мы уже видели, s etXxx методы поддержки сужения для примитивных типов. Важно отметить, что мы должны обеспечить правильную цель для сужения, чтобы быть успешным . В противном случае, JVM бросает НезаконныеАргументЭксцепция :

@Test
public void givenInt_whenSetLongField_thenIllegalArgumentException() 
  throws Exception {
    Person person = new Person();

    Field pinCodeField = person.getClass()
        .getDeclaredField("pinCode");
    pinCodeField.setAccessible(true);

    long pinCode = 411057L;

    Assertions.assertThrows(IllegalArgumentException.class, () -> pinCodeField.setLong(person, pinCode));
}

4.2. НезаконноеприемкаКцепция

Если мы пытаемся установить частные поле, которое не имеет прав доступа , то JVM будет бросать НезаконныеАцессЭксцепция . В приведеном выше примере, если мы не напишем заявление nameField.setAccessible (правда) , то JVM бросает исключение:

@Test
public void whenFieldNotSetAccessible_thenIllegalAccessException() 
  throws Exception {
    Person person = new Person();
    Field nameField = person.getClass()
        .getDeclaredField("name");

    Assertions.assertThrows(IllegalAccessException.class, () -> nameField.set(person, "Umang Budhwar"));
}

5. Заключение

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

Как всегда, полный код для этого примера доступен более на GitHub .