Там какой-либо путь состоит в том, чтобы изменить значение 'частного статического заключительного' поля в Java снаружи класса?

использовать коррелированный подзапрос

  select t1.* from mytable t1
  where not exists ( select 1 from mytable t2 where t2.column2=t1.column2 and column1='A')

или использовать not in

select t1.* from table_name t1 where t1.column2 not in ( select column2 from table_name where column1='A')
11
задан AstroCB 30 August 2014 в 21:07
поделиться

9 ответов

Это возможно. Я использовал это, чтобы monkeypatch порочные потоки, которые предотвращали выгрузку классов в веб-приложениях. Вам просто нужно использовать отражение, чтобы удалить модификатор final , затем вы можете изменить поле.

Что-то вроде этого поможет:

private void killThreadLocal(String klazzName, String fieldName) {
    Field field = Class.forName(klazzName).getDeclaredField(fieldName);
    field.setAccessible(true);  
    Field modifiersField = Field.class.getDeclaredField("modifiers");
    modifiersField.setAccessible(true);
    int modifiers = modifiersField.getInt(field);
    modifiers &= ~Modifier.FINAL;
    modifiersField.setInt(field, modifiers);
    field.set(null, null);
}

Также есть некоторое кеширование вокруг Field #set , поэтому, если какой-то код выполнялся раньше, он может не обязательно работать ....

10
ответ дан 3 December 2019 в 07:39
поделиться

Любая инфраструктура AOP будет соответствовать вашим потребностям

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

Jmockit использует инфраструктуру ASM для того же.

5
ответ дан 3 December 2019 в 07:39
поделиться

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

Field field = SomeClass.class.getDeclareField("INSTANCE");
field.setAccessible(true); // what security. ;)
field.set(null, newValue);
1
ответ дан 3 December 2019 в 07:39
поделиться

Если вы действительно должны (хотя для нашей проблемы я бы посоветовал вам использовать решение CaptainAwesomePants) вы мог бы взглянуть на JMockIt . Хотя это предназначено для использования в модульных тестах, если позволяет переопределить произвольные методы. Это делается путем изменения байт-кода во время выполнения.

1
ответ дан 3 December 2019 в 07:39
поделиться

Я предвосхищу этот ответ, признав, что на самом деле это не ответ на заданный вами вопрос об изменении приватного статического финала поле. Однако в приведенном выше конкретном примере кода я могу сделать так, чтобы вы могли переопределить doSomething (). Что вы можете сделать, так это воспользоваться тем, что getInstance () является открытым методом и подклассом:

public class MySomeClass extends SomeClass
{
   private static final INSTANCE = new MySomeClass();

   public SomeClass getInstance() {
        return INSTANCE;
   }

   public Object doSomething() {
      //Override behavior here!
   }
}

Теперь просто вызовите MySomeClass.getInstance () вместо SomeClass.getInstance (), и все готово. Конечно, это работает, только если вы тот, кто вызывает getInstance (), а не какую-то другую часть неизменяемого материала, с которым вы работаете.

0
ответ дан 3 December 2019 в 07:39
поделиться

Если нет Доступен внешний взлом (по крайней мере, я не в курсе) Я бы взломал сам класс. Измените код, добавив необходимую проверку безопасности. Так как это внешняя библиотека, вы не будете регулярно получать обновления, также не так много обновлений в любом случае. Всякий раз, когда это происходит, я с радостью могу сделать это заново, так как в любом случае это не большая задача.

-1
ответ дан 3 December 2019 в 07:39
поделиться

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

РЕДАКТИРОВАТЬ: это возможно, но не очень хорошая идея.

http://java.sun.com/docs/books/jni/html/pitfalls.html

10.9 Нарушение правил контроля доступа

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

Собственный код, который обходит проверки доступа на уровне исходного языка может иметь нежелательные последствия для выполнение программы. Например, несоответствие может быть создано, если нативный метод изменяет конечное поле после JIT-компилятора имеет встроенный доступ к полю. Аналогично, нативные методы не должны изменить неизменяемые объекты, такие как поля в случаях java.lang.String или java.lang.Integer. Это может привести к поломке инварианты в платформе Java реализация.

1
ответ дан 3 December 2019 в 07:39
поделиться

Здесь ваша проблема - старый добрый Инъекция зависимостей (иначе говоря, инверсия контроля). Ваша цель должна заключаться в том, чтобы внедрить вашу реализацию SomeClass вместо того, чтобы устанавливать ее вручную. И да, этот подход требует некоторых изменений в вашем существующем дизайне, но по правильным причинам (назовите ваш любимый принцип дизайна здесь) - особенно один и тот же объект не должен отвечать за создание и использование других объектов.

Я предполагаю, что вы используете SomeClass выглядит примерно так:

public class OtherClass {
  public void doEverything() {
    SomeClass sc = SomeClass.geInstance();
    Object o = sc.doSomething();

    // some more stuff here...
  }
}

Вместо этого вам следует сначала создать свой класс, который реализует тот же интерфейс или расширяет SomeClass и затем передать этот экземпляр в doEverything () , чтобы ваш класс стал независимым от реализации SomeClass . В этом случае код, который вызывает doEverything , ответственен за передачу в правильной реализации - будь то фактический SomeClass или ваш обезьяновый патч MySomeClass .

public class MySomeClass() extends SomeClass {
  public Object doSomething() {
    // your monkeypatched implementation goes here
  }
}

public class OtherClass {
  public void doEveryting(SomeClass sc) {
    Object o = sc.doSomething();

    // some more stuff here...
  }
}
-1
ответ дан 3 December 2019 в 07:39
поделиться

на mockito очень прост:

import static org.mockito.Mockito.*;

public class SomeClass {

    private static final SomeClass INSTANCE = new SomeClass();

    public static SomeClass getInstance() {
        return INSTANCE;
    }

    public Object doSomething() {
        return "done!";
    }

    public static void main(String[] args) {
        SomeClass someClass = mock(SomeClass.getInstance().getClass());
        when(someClass.doSomething()).thenReturn("something changed!");
        System.out.println(someClass.doSomething());
    }
}

этот код печатает «что-то изменилось!»; Вы можете легко заменить свои экземпляры-одиночки. Мои 0,02 цента.

0
ответ дан 3 December 2019 в 07:39
поделиться
Другие вопросы по тегам:

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