Which Java image should be used in ambiguous cases?

I'm having trouble porting Wicket 1.3 -> Wicket 1.4, but this question can also be applied to Java generics. The migration triggered hundreds of spring warnings from nowhere - for those unfamiliar with Wicket, many Wicket classes come from a common ancestor, which was changed in version 1.4, and I'm not sure which options to apply in some cases, mostly different forms and tables . I think they can do with <?> , <Object> or <Void> , but I'm not sure which one.

<?> seems to me most suitable, but there are many places where I cannot use a wildcard. <Object> works in all cases, but it makes me worried because it basically writes a wildcard without using a wildcard, which just feels inherently wrong for part of my brain. And the use of <Void> been suggested in the Wicket Migration Guide .

So what should be done in this case?


EDIT 2: I think my first edit (now at the bottom of the question) confused people, giving the impression that I was just asking about line sets. Here are some more examples and their warnings:

 public class DocumentProcessor extends Form implements DocumentManagement { ... 

The form is a raw type. References to the generic type. The form must be parameterized.

 AjaxFallbackDefaultDataTable theTable = new AjaxFallbackDefaultDataTable("theTable", cols, dataProvider, recPerPg); 

Several markers on this line
- Security type: constructor AjaxFallbackDefaultDataTable (String, List, ISortableDataProvider, int) refers to the raw type AjaxFallbackDefaultDataTable. References to the generic type AjaxFallbackDefaultDataTable should be parameterized
- AjaxFallbackDefaultDataTable is a raw type. References to the generic type AjaxFallbackDefaultDataTable should be parameterized
- AjaxFallbackDefaultDataTable is a raw type. References to the generic type AjaxFallbackDefaultDataTable should be parameterized


EDIT: I was hoping the question would be so broad that he didn't need a sample code, but here are some of them.

 List<IColumn> columns = new ArrayList<IColumn>(); columns.add(new PropertyColumn(new Model<String>("Number"), "revisionID")); 

These warnings are generated:

Several markers in the [first] line
- IColumn is a raw type. References to the generic IColumn type should be parameterized
- IColumn is a raw type. References to the generic IColumn type should be parameterized

Several markers in the [second] line
- Security type: the constructor PropertyColumn (IModel, String) refers to the raw type PropertyColumn. References to the generic PropertyColumn type should be parameterized
- PropertyColumn is a raw type. References to the generic PropertyColumn type should be parameterized

There are no errors.

+4
source share
6 answers

Use Void if you are not going to use the component underlying the model object.

Semantically, it sounds more and better conveys the idea that it is not that the model object can be anything, but that it will semantically never be used . The Void keyword is mainly used as a normal solution in a similar situation.

If you are going to use a model object and do not care about which I do not think you had in mind ** use wildcards where you can ** and where you cannot (constructor arguments, etc.), or Void, Object, or perhaps some other "encompassing" class that makes a decision based on your specific semantics of the component and the desired typical typing (as an example, in the case of a constructor for a component variable, you might think about what your constructor using Void or Object).

Of course, from the point of view of the theory of “good programming theory”, in practice, you don’t have to care much, although such thinking can help your teammates support your code and can help you better understand it, maybe even predict errors.

The use of wildcards is ubiquitous among wicket users, perhaps even more common than the solution I suggested, but this is not because wildcards are an agreement, but most likely simply because of most code examples that pop up in search engines Preferred Wildcards. Nevertheless, since the proposal of the guide on migration from Void shows that not only characters with separator characters are less semantically coherent, but they do not seem to be an absolute agreement, even, it seems, by gate developers who are quite aware of the internal work their types so that their recommendations are taken seriously.

+3
source

Alternatives available:

  • To just use a raw type, as in your code example, just ignore the warnings
  • To use a wildcard / generic object
  • To use advanced shared

I proceed from your question that No. 1 is not a viable option for you.

Example for # 2 (wildcard / object)

 List<IColumn<?>> columns = new ArrayList<IColumn<?>>(); 

OR

 List<IColumn<Object>> columns = new ArrayList<IColumn<Object>>(); 

IMO I don’t think it really matters, do you choose ? or Object , and none of them is more correct than the other, at least functionally.
If you do not care what is generic, and you never turn to it, then it almost matters; although think in advance if it’s really possible, you will use generics here in the future. This will probably only happen if you do not need to output anything from IColumn objects in your pre-migration code.

Example for # 3 (extends the general)

Create a supertype or common interface for all possible generics like IColumn . Where
T extends MyType :

 List<IColumn<T>> columns = new ArrayList<IColumn<T>>(); 

I would define a solution when choosing between the 2nd and 3rd ways of what are the possible common attributes for IColumn .

  • If they are your own classes. And , you really want to access objects of a generic type, I would go for the third method,
  • otherwise, for example, with String or boxed primitives such as Integer , or if you are not considering objects of a generic type, I would go for method 2.

NTN

+1
source

Semantically, using <?> Means "I don't know the type, and I really don't care. Using anything else sets expectations in the form of expected content. In practice, <Object> does the same, but claims that you will use properties their general type, which use the type of the parameter.

So, the rule of thumb should be:

  • If you work only with a genetic object, but not with parameterized content, use <?> So that you know at a glance that the parameter does not matter for behavior.
  • in any other case, use the most specific parameter, which covers all the types with which your method is intended. Extreme case of <Object> , others include <? extends SomeTopLevelType> <? extends SomeTopLevelType>
+1
source

I have not used wickets, and Vodafone blocks me from viewing API documents. However, it seems like you are missing many common arguments and you need something like:

 List<IColumn<String>> columns = new ArrayList<IColumn<String>>(); columns.add(new PropertyColumn<String>(new Model<String>("Number"), "revisionID")); 

If you want to add another IColumn with an unrelated common argument, you will need something like:

 List<IColumn<?>> columns = new ArrayList<IColumn<?>>(); columns.add(new PropertyColumn<String>(new Model<String>("Number"), "revisionID")); 

Or, if you need to get the properties of a column, perhaps something like:

 List<IColumn<String>> strColumns = new ArrayList<IColumn<String>>(); List<IColumn<?>> columns = new ArrayList<IColumn<?>>(); PropertyColumn<String> column = new PropertyColumn<String>(new Model<String>("Number"), "revisionID"); strColumns.add(column); columns.add(column); 
0
source

You want to use the model type associated with your component. That is, use the type returned by the call to getModelObject (). So, to use the example from the migration guide:

 ListView<Person> peopleListView = new ListView<Person>("people", people) { protected void populateItem(ListItem<Person> item) { item.add(new Link<Person>("editPerson", item.getModel()){ public void onClick() { Person p = getModelObject(); setResponsePage(new EditPersonPage(p)); } }); } }; 

Using generics, it’s easy to say that this is a list of faces, with a link to an edit page in which a person is used when he is being modeled. Unfortunately, very often at the gate your components will not have a model associated with them. In this case, getModel () will return null, so the appropriate type would be <Void> , which is essentially a place holder for null.

DocumentProcessor

 public class DocumentProcessor extends Form implements DocumentManagement { ... 

If you do not install a model for DocumentProcessor, it will look like this:

 public class DocumentProcessor extends Form<Void> implements DocumentManagement { public DocumentProcessor(String id) { super(id); .... 

but with the DocumentProcessor model it looks something like this:

 public class DocumentProcessor extends Form<Document> implements DocumentManagement { public DocumentProcessor(String id, Document doc) { super(id, doc); 

AjaxFallbackDefaultDataTable

Judging by its constructors, AjaxFallbackDefaultDataTable will most likely save either the IColumn [] model or List in it, but for your implementation you don’t know or don’t care, therefore <?> suitable, the difference between this and DocumentProcessor is re extending form and therefore know and care about how it uses this model.

Icolumn

In the IColumn / PropertyColumn example, I assume that the revisionID field is long, then I would write it like this:

 List<PropertyColumn> columns = new ArrayList<PropertyColumn>(); columns.add(new PropertyColumn<Long>(new Model<String>("Number"), "revisionID")); 

You can watch

Details 1.4 Migration Information

Type parameter

0
source

The warnings say that the IColumn interface and the PropertyColumn class are parameterized types, so you just need to define type parameters for them.

Consider the following example:

 List<Set> list = new ArrayList<Set>(); 

List and ArrayList are parameterized types and their type parameters are defined. However, Set is also parameterized, but the original version is used as a type parameter, so the compiler generates a warning in this case.

We can fix our example by explicitly specifying all type arguments, for example.

 List<Set<Integer>> list1 = new ArrayList<Set<Integer>>(); List<Set<String>> list1 = new ArrayList<Set<String>>(); 

You need to do the same for your common classes and interfaces.

-one
source

All Articles