Общий тип и проблема с подстановочными знаками в java [duplicate]

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

Предположим, у вас есть веб-форма Contact.aspx, чей класс codebehind Свяжитесь с вами, и у вас есть имя объекта Contact.

Затем следующий код вызовет исключение NullReferenceException при вызове context.SaveChanges ()

Contact contact = new Contact { Name = "Abhinav"};
var context = new DataContext();
context.Contacts.Add(contact);
context.SaveChanges(); // NullReferenceException at this line

Ради полноты класса DataContext

public class DataContext : DbContext 
{
    public DbSet Contacts {get; set;}
}

и класс сущности контакта. Иногда классы сущностей являются частичными классами, так что вы можете распространять их и в других файлах.

public partial class Contact 
{
    public string Name {get; set;}
}

Ошибка возникает, когда оба класса entity и codebehind находятся в одном и том же пространстве имен. Чтобы исправить это, переименуйте класс сущности или класс codebehind для Contact.aspx.

Причина. Я все еще не уверен в причине. Но всякий раз, когда какой-либо из классов сущностей расширяет System.Web.UI.Page, возникает эта ошибка.

Для обсуждения рассмотрим NullReferenceException в DbContext.saveChanges ()

9
задан Powerlord 26 August 2010 в 14:48
поделиться

5 ответов

Используйте следующее:

Msg<? extends Value<?>> someMsg = strMsg;

Проблема в том, что ? в Msg<Value<?>> objMsg является NOT , способным преобразовать захват. Это не «f6] из Value из типа . Это« Msg из Value типа ЛЮБОЙ ».

Это также объясняет, почему вместе с изменением объявления я также переименовал переменную в someMsg. Value не может быть просто Object. Он должен принадлежать некоторым типу (String в этом примере).


Более общий пример

Рассмотрим более общий пример List<List<?>>. Аналогично исходному сценарию a List<List<?>> can NOT capture-convert a List<List<Integer>>.

    List<List<Integer>> lolInt = null;

    List<List<?>> lolAnything = lolInt;         // DOES NOT COMPILE!!!
    // a list of "lists of anything"

    List<? extends List<?>> lolSomething = lolInt;   // compiles fine!
    // a list of "lists of something"

Вот еще один способ взглянуть на это:

  • Java generics is (g16) Integer - Number , но List< Integer > не является List< Number > Аналогичным образом, List<Integer> может быть захвачен захватом с помощью List<?> , но List< List<Integer> > не является List< List<?> >
  • Использование ограниченного шаблона , List<? extends  Number > может захватывать-преобразовать a List< Integer > S аналогично List<? extends  List<?> > может захватывать-преобразовать List< List<Integer> >

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

    List<List<?>> lolAnything = new ArrayList<List<?>>(); // compiles fine!

    List<?> listSomething = new ArrayList<?>(); // DOES NOT COMPILE!!!
        // cannot instantiate wildcard type with new!

Связанные вопросы

См. также

17
ответ дан Community 27 August 2018 в 02:49
поделиться

Хотя ваш общий параметр типа содержит подстановочный знак, он сам по себе не является подстановочным знаком. При назначении переменной (Msg<T>) с несимвольным общим типом T назначенный объект должен иметь ровно T в качестве своего общего типа (включая все параметры типового типа T, подстановочные знаки и несимметричные типы, подстановочные). В вашем случае T есть Value<String>, который не является тем же типом, что и Value<?>.

Что вы можете сделать, поскольку Value<String> назначается Value<?>, использует тип подстановочного знака :

Msg<? extends Value<?>> a = new Msg<Value<String>>();
3
ответ дан ILMTitan 27 August 2018 в 02:49
поделиться

Не прямой ответ, но я настоятельно рекомендую прочитать: http://java.sun.com/j2se/1.5/pdf/generics-tutorial.pdf , чтобы лучше понять дженерики.

1
ответ дан Manuel Selva 27 August 2018 в 02:49
поделиться

У ILMTitan есть хорошее решение, и если вы не хотите, чтобы класс имел значение Value, вы можете использовать базовый тип вместо дженериков в этот момент, потому что вы отключите функцию безопасности, но там вдали. Вы даже можете передать параметр, чтобы сделать этот метод более общим, но ключ - «@SuppressWarnings».

@SuppressWarnings("unchecked")
Msg<Value<?>> convert()
{
    return (Msg<Value<?>>) this;
}
0
ответ дан Peter DeWeese 27 August 2018 в 02:49
поделиться

Мой ответ похож на другой, но, надеюсь, более ясен.

List<List<?>> is a list of (lists of anything).

List<List<String>> is a list of (lists of strings).

Последнее не может быть преобразовано в первое, потому что это позволит вам добавить список & lt; Number & gt; в ваш список & lt; List & lt; String & gt; & gt ;, который будет явно нарушен.

Обратите внимание, что правила для этого не изменяются, если вы заменяете List некоторым типом, который не имеет .add. Для Java понадобится ковариация сайта-адресата и / или контравариантность (например, C # IEnumerable & lt; out T & gt; или Scala's List [+ A]). Java имеет только ковариацию и контравариантность сайта (? Расширяет X,? Супер X).

3
ответ дан Ricky Clarkson 27 August 2018 в 02:49
поделиться
Другие вопросы по тегам:

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