Как я определяю неизменные объекты в Java

Функция

seaborn, работающая на одном оси, может принимать один аргумент.

Например, документы в seaborn.kdeplot включают в себя:

ax : matplotlib axis, optional
    Axis to plot on, otherwise uses current axis

Итак, если вы это сделали:

df = function_to_load_my_data()
fig, ax = plt.subplots()

Тогда вы можете:

seaborn.kdeplot(df['col1'], ax=ax)
seaborn.kdeplot(df['col2'], ax=ax)

41
задан mcherm 16 October 2008 в 00:10
поделиться

11 ответов

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

единственный способ быть рядом с этим:

  • Только позволяют заключительные свойства типов, которые неизменны (типы примитивов и классы, которые Вы знаете, неизменны),
  • Требуют, чтобы класс для финала сам
  • Потребовал, чтобы они наследовались базовому классу, который Вы обеспечиваете (который, как гарантируют, будет неизменен)

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

static boolean isImmutable(Object obj) {
    Class<?> objClass = obj.getClass();

    // Class of the object must be a direct child class of the required class
    Class<?> superClass = objClass.getSuperclass();
    if (!Immutable.class.equals(superClass)) {
        return false;
    }

    // Class must be final
    if (!Modifier.isFinal(objClass.getModifiers())) {
        return false;
    }

    // Check all fields defined in the class for type and if they are final
    Field[] objFields = objClass.getDeclaredFields();
    for (int i = 0; i < objFields.length; i++) {
        if (!Modifier.isFinal(objFields[i].getModifiers())
                || !isValidFieldType(objFields[i].getType())) {
            return false;
        }
    }

    // Lets hope we didn't forget something
    return true;
}

static boolean isValidFieldType(Class<?> type) {
    // Check for all allowed property types...
    return type.isPrimitive() || String.class.equals(type);
}

Обновление: , Как предложено в комментариях, это могло быть расширено для рекурсивного вызова суперкласс вместо того, чтобы проверить на определенный класс. Было также предложено рекурсивно использовать isImmutable в isValidFieldType Методе. Это могло, вероятно, работать, и я также сделал некоторое тестирование. Но это не тривиально. Вы не можете только проверить все типы поля с вызовом к isImmutable, потому что Строка уже проваливает этот тест (его поле hash не является окончательным!). Также Вы легко сталкиваетесь с бесконечными рекурсиями, вызывая StackOverflowErrors;) Другие проблемы могли бы быть вызваны дженериками, где также необходимо проверить их типы на неизменность.

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

29
ответ дан Simon Lehmann 4 August 2019 в 20:53
поделиться

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

0
ответ дан Peter Lawrey 4 August 2019 в 20:53
поделиться

Выезд joe-e, реализация возможностей Java.

0
ответ дан 4 August 2019 в 20:53
поделиться

Можно Попросить, чтобы клиенты добавили метаданные (аннотации) и проверили их во времени выполнения с отражением, как это:

Метаданные:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.CLASS)
public @interface Immutable{ }

Клиентский Код:

@Immutable
public class ImmutableRectangle {
    private final int width;
    private final int height;
    public ImmutableRectangle(int width, int height) {
        this.width = width;
        this.height = height;
    }
    public int getWidth() { return width; }
    public int getHeight() { return height; }
}

Тогда при помощи отражения о классе, проверьте, имеет ли это аннотацию (я вставил бы код, но его шаблон и может быть найден легко онлайн)

3
ответ дан Pablo Fernandez 4 August 2019 в 20:53
поделиться

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

я просто представил бы интерфейс "Immutable" для проверки по при добавлении. Это работает подсказкой, что только неизменные объекты должны быть вставлены по любой причине, Вы делаете ее.

interface Immutable {}

class MyImmutable implements Immutable{...}

public void add(Object o) {
  if (!(o instanceof Immutable) && !checkIsImmutableBasePrimitive(o))
    throw new IllegalArgumentException("o is not immutable!");
  ...
}
2
ответ дан Daniel Hiller 4 August 2019 в 20:53
поделиться

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

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

предположим у Вас есть этот класс:

class Foo {
  final String x;
  final Integer y;
  ...

  public bar() {
    Singleton.getInstance().foolAround();
  }
}

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

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

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

class A {
  final B b; // might be immutable...
}

class B {
  final A a; // same so here.
}

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

можно зафиксировать это с 'замеченной' картой, которая запрещает циклы, или с некоторым действительно умным кодом, который решает, что классы неизменны, если все их dependees неизменны только в зависимости от себя, но это будет действительно сложным...

4
ответ дан Martin Probst 4 August 2019 в 20:53
поделиться

Это могло быть другой подсказкой:

, Если класс не имеет никаких методов set тогда, он не может быть видоизменен, предоставлен параметры, с которыми он был создан, или "примитивные" типы или не изменяемые сами.

Также никакие методы не могли быть переопределены, все поля окончательные и частными,

я попытаюсь кодировать что-то завтра для Вас, но код Simon с помощью отражения выглядит довольно хорошим.

В среднее время пытаются захватить копию "Эффективного Java" книга Josh Block, этому связали Объект с этой темой. В то время как, наверняка не говорит, как обнаружить inmmutable класс, он показывает, как создать хороший.

объект называют: "Неизменность пользы"

ссылка: http://java.sun.com/docs/books/effective/

4
ответ дан OscarRyz 4 August 2019 в 20:53
поделиться

В основном нет.

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

Редактирование: Другие люди предложили иметь неизменную аннотацию. Это прекрасно, но Вам нужна документация также. Иначе люди будут просто думать, "если я поместил эту аннотацию на свой класс, я могу сохранить его в наборе" и просто зажму его на чем-либо, неизменные и изменяемые классы одинаково. На самом деле я опасался бы иметь неизменную аннотацию на всякий случай, люди думают, что аннотация делает их класс неизменный.

8
ответ дан SCdF 4 August 2019 в 20:53
поделиться

Используйте Неизменный аннотация от Параллелизм Java на практике . Инструмент FindBugs может тогда помочь в обнаружении классов, которые изменяемы, но не должны быть.

29
ответ дан beresfordt 4 August 2019 в 20:53
поделиться

почему делают все рекомендации требуют, чтобы класс был окончательным? если Вы используете отражение для проверки класса каждого объекта, и можно решить программно, что тот класс неизменен (неизменные, заключительные поля), то Вы не должны требовать, чтобы сам класс был окончательным.

3
ответ дан james 4 August 2019 в 20:53
поделиться

В моей компании мы определили Атрибут, названный @Immutable. Если Вы принимаете решение присоединить это к классу, это означает, что Вы обещаете, что Вы неизменны.

Это работает на документацию, и в Вашем случае это работало бы фильтром.

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

9
ответ дан Jason Cohen 4 August 2019 в 20:53
поделиться
Другие вопросы по тегам:

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