Общая безопасность Vararg [дубликат]

Вы можете использовать эту пользовательскую библиотеку (написанную с помощью Promise) для выполнения удаленного вызова.

function $http(apiConfig) {
    return new Promise(function (resolve, reject) {
        var client = new XMLHttpRequest();
        client.open(apiConfig.method, apiConfig.url);
        client.send();
        client.onload = function () {
            if (this.status >= 200 && this.status < 300) {
                // Performs the function "resolve" when this.status is equal to 2xx.
                // Your logic here.
                resolve(this.response);
            }
            else {
                // Performs the function "reject" when this.status is different than 2xx.
                reject(this.statusText);
            }
        };
        client.onerror = function () {
            reject(this.statusText);
        };
    });
}

Пример простого использования:

$http({
    method: 'get',
    url: 'google.com'
}).then(function(response) {
    console.log(response);
}, function(error) {
    console.log(error)
});
345
задан MarmiK 30 July 2014 в 08:04
поделиться

5 ответов

Загрязнение кучи - технический термин. Он ссылается на ссылки, которые имеют тип, который не является супертипом объекта, на который они указывают.

List<A> listOfAs = new ArrayList<>();
List<B> listOfBs = (List<B>)(Object)listOfAs; // points to a list of As

Это может привести к «необъяснимому» ClassCastException s.

// if the heap never gets polluted, this should never throw a CCE
B b = listOfBs.get(0); 

@SafeVarargs не мешает этому вообще. Однако есть методы, которые, предположительно, не будут загрязнять кучу, компилятор просто не может это доказать. Раньше абоненты таких API бы раздражали предупреждения, которые были совершенно бессмысленны, но должны были быть подавлены на каждом сайте вызова. Теперь автор API может подавить его один раз на сайте объявления.

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

203
ответ дан Ben Schulz 27 August 2018 в 09:40
поделиться

Когда вы объявляете

public static <T> void foo(List<T>... bar), компилятор преобразует его в

public static <T> void foo(List<T>[] bar), затем в

public static <T> void foo(List[] bar)

Тогда возникает опасность, что вы ошибочно назначите неверные значения в списке, а компилятор не вызовет никаких ошибок. Например, если T является String, тогда следующий код будет компилироваться без ошибок, но не будет работать во время выполнения:

// First, strip away the array type (arrays allow this kind of upcasting)
Object[] objectArray = bar;

// Next, insert an element with an incorrect type into the array
objectArray[0] = Arrays.asList(new Integer(42));

// Finally, try accessing the original array. A runtime error will occur
// (ClassCastException due to a casting from Integer to String)
T firstElement = bar[0].get(0);

Если вы рассмотрели метод, чтобы убедиться, что он не содержит таких уязвимостей, то вы можете аннотировать его с помощью @SafeVarargs для подавления предупреждения. Для интерфейсов используйте @SuppressWarnings("unchecked").

Если вы получите это сообщение об ошибке:

Метод Varargs может привести к загрязнению кучи от невосстанавливаемого параметра varargs

, и вы уверены, что ваше использование безопасно, тогда вы должны использовать @SuppressWarnings("varargs"). См. . Является ли @SafeVarargs подходящей аннотацией для этого метода? и https://stackoverflow.com/a/14252221/14731 для приятного объяснения этого второго рода ошибок.

Ссылки:

180
ответ дан Community 27 August 2018 в 09:40
поделиться

@SafeVarargs не мешает ему произойти, однако он требует, чтобы компилятор был более строгим при компиляции кода, который его использует.

http://docs.oracle.com/javase/7/docs/api/java/lang/SafeVarargs.html объясняет это более подробно.

Загрязнение кучи - это когда вы получаете ClassCastException при выполнении операции на общем интерфейсе, и он содержит другой тип, чем объявлено.

6
ответ дан jontro 27 August 2018 в 09:40
поделиться

Когда вы используете varargs, это может привести к созданию Object[] для хранения аргументов.

Из-за анализа escape-кода JIT может оптимизировать создание этого массива. (Один из немногих раз, когда я нашел, что это так). Его не гарантируют оптимизацию, но я бы не стал беспокоиться об этом, если вы не видите его проблемы в профилировщике памяти.

AFAIK @SafeVarargs подавляет предупреждение компилятором и не изменяет поведение JIT.

5
ответ дан Peter Lawrey 27 August 2018 в 09:40
поделиться

Причина в том, что varargs дают возможность вызова с непараметризированным массивом объектов. Поэтому, если ваш тип был List & lt; A> ..., его также можно вызвать с помощью типа List [] non-varargs.

Вот пример:

public static void testCode(){
    List[] b = new List[1];
    test(b);
}

@SafeVarargs
public static void test(List<A>... a){
}

Как вы можете видеть List [] b может содержать любого типа потребителя, и все же этот код компилируется. Если вы используете varargs, то вы в порядке, но если вы используете определение метода после type-erasure - void test (List []), то компилятор не будет проверять типы параметров шаблона. @SafeVarargs подавит это предупреждение.

0
ответ дан user1122069 27 August 2018 в 09:40
поделиться
Другие вопросы по тегам:

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