Java Универсальный Список <Список <? расширяет Число>>

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

Весь приведенный ниже код добавляется в конце функции обновления в файле dndTree.js.

console.log(root); //root contains everything you need
    const getCircularReplacer = (deletePorperties) => { //func that allows a circular json to be stringified
      const seen = new WeakSet();
      return (key, value) => {
        if (typeof value === "object" && value !== null) {
          if(deletePorperties){
            delete value.id; //delete all properties you don't want in your json (not very convenient but a good temporary solution)
            delete value.x0;
            delete value.y0;
            delete value.y;
            delete value.x;
            delete value.depth;
            delete value.size; 
          }
          if (seen.has(value)) {
            return;
          }
          seen.add(value);
        }
        return value;
      };
    };

    var myRoot = JSON.stringify(root, getCircularReplacer(false)); //Stringify a first time to clone the root object (it's allow you to delete properties you don't want to save)
    var myvar= JSON.parse(myRoot);
    myvar= JSON.stringify(myvar, getCircularReplacer(true)); //Stringify a second time to delete the propeties you don't need

    console.log(myvar); //You have your json in myvar

Теперь, когда у вас есть JSON, вы можете:

  • Скачать новый файл tree.json:

     function download(content, fileName, contentType) {
       var a = document.createElement("a");
       var file = new Blob([content], {
         type: contentType
       });
       a.href = URL.createObjectURL(file);
       a.download = fileName;
       a.click();
     }
     download(myvar, 'tree.json', 'text/plain'); 
    
  • [ 1110] Или вы можете прямо написать в своем файле.

Пример с node.js:

    var fs = require('fs');
    fs.writeFile("tree.json", myvar, function(err) {
      if (err) {
        console.log(err);
      }
    });

Проверьте это для получения дополнительной информации для сохранения файла: Как сохранить JSON в локальный текстовый файл

39
задан Michael Myers 29 April 2009 в 14:45
поделиться

4 ответа

В Java, если Car является производным классом Vehicle , тогда мы можем рассматривать все Cars как Vehicles ; Автомобиль - это Автомобиль . Однако, Список из Автомобили также не является Список из Транспортных средств . Мы говорим, что List не является не ковариантным с List .

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

List<List<? extends Number>> l = new ArrayList<List<Number>>();
//        ----------------                          ------
// 
// "? extends Number" matched by "Number". Success!

Внутренний Список работает, потому что номер действительно расширяет номер , поэтому он соответствует «? Extends Number ». Все идет нормально. Что дальше?

List<List<? extends Number>> l = new ArrayList<List<Number>>();
//   ----------------------                    ------------
// 
// "List<? extends Number>" not matched by "List<Number>". These are
//   different types and covariance is not specified with a wildcard.
//   Failure.

Однако объединенный параметр внутреннего типа List не соответствует List ; типы должны быть точно идентичными . Другой подстановочный знак скажет Java, что этот комбинированный тип также должен быть ковариантным:

List<? extends List<? extends Number>> l = new ArrayList<List<Number>>();
73
ответ дан John Feminella 27 November 2019 в 02:29
поделиться

I Я не очень знаком с синтаксисом Java, но, похоже, ваша проблема заключается в следующем:

Ковариантность и Контравариантность

3
ответ дан eulerfx 27 November 2019 в 02:29
поделиться

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

public void doThingWithList(List<List<? extends Number>> list);

позволяет вам передать List или List .

public void doThingWithList(List<List<Number>> list);

позволяет передавать только аргументы, объявленные как List . Небольшое различие, да, но использование подстановочного знака является мощным и безопасным . Вопреки тому, как это может показаться, список не является подклассом или не может быть назначен из List . Также List не является подклассом List , поэтому приведенный выше код не компилируется.

3
ответ дан Steve Reed 27 November 2019 в 02:29
поделиться

Ваше утверждение не компилируется, поскольку List отличается от типа List . Первый является супертипом второго.

Вы пробовали это? Здесь я выражаю, что List является ковариантным в своем аргументе типа, поэтому он будет принимать любой подтип из List (который включает в себя список <номер> ).

List<? extends List<? extends Number>> aList = new ArrayList<List<Number>>();

Или даже это. Здесь параметр типа для ArrayList с правой стороны совпадает с параметром типа с левой стороны, поэтому дисперсия не является проблемой.

List<List<? extends Number>> aList = new ArrayList<List<? extends Number>>();

Вы можете просто сказать

List<List<Number>> aList = new ArrayList<List<Number>>();

Я склонен по возможности избегайте подстановочных знаков типа ? . Я считаю, что затраты, понесенные при аннотации типа, не стоят выгоды.

2
ответ дан Apocalisp 27 November 2019 в 02:29
поделиться
Другие вопросы по тегам:

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