How to specify that the constructor type is equal to the one declared in the class?

Asked

Viewed 249 times

6

I created an object that accepts a list of any kind, like this:

class Grid<T> {
    private Integer count;
    private Integer offset;
    private Integer limit;
    private List<T> list;

    private T tipo;

    public Grid() {
    }

    public Grid(Integer count, List<T> list) {
        this.count = count;
        this.list = list;
    }
}

However, in this way it allows me to create an object of one type and pass in the constructor another type, like this:

List<Usuario> listaUsuarios = new ArrayList<>();
Grid<Empresa> grid = new Grid(10, listaUsuarios);

I mean, I created a grid like Empresa, and I ran the constructor through a list of the Usuario.

There is already a setList(List<T> list) it works as expected, ie, it only accepts if the list is of the same type as declared in class.

How can I require the constructor’s list to be equal to that stated in the class? That is, if you create a Grid<Empresa> in the constructor it should only accept a list of the type List<Empresa>.

  • Loco. Are you sure about this? I don’t know Java so deep to talk about it, but for me this form is correct and should restrict. I imagine I’m wrong and someone will tell you what to do.

  • This is the correct form. Perhaps you are wondering why the IDE does not see it as a compilation error, which in fact it is not. Try to run your program exactly as shown and you will see that you will be released an exception referring to the type reported to be different.

  • @Diegofelipe, just instantiating in this way did not give error neither compilation nor execution. However, when trying to fetch an item from the list, it gave Cast error, which is correct...

  • You see you’re wearing List and not ArrayList? Anyway how about doing an MCVE?

  • @bigown believe this is not even the problem, because Arraylist implements List, so it is not incorrect. From what I understand, he wants to block in the constructor pass a list of a different kind, the only way I know how to do this is using interface, but since I don’t really understand interfaces, maybe someone with more experience can explain better.

  • I don’t think so and I don’t think interface has anything to do with it.

  • @Earendul take a look at this file, see if this addresses your problem. http://www.inf.pucrs.br/flash/alpro2/present/U03_projeto/01b-genericos/handout.html#generic

  • I did a test and it really happens. What a mess. I did it in C# and it doesn’t even compile because the guy is wrong. Now I want to see how to solve this.

  • The Eclipse gives the following information Type safety: The expression of type Grid needs unchecked conversion to conform to Grid<Empresa> in new Grid(10, listaUsuarios);

  • @Diegofelipe read the file, but still do not know how to solve the problem. Maybe only even avoiding receiving the list in the constructor and only in the set.

  • @ramaral And Netbeans warns nothing..

  • @I also want to see how you solve this, :)

  • Possible cause of the problem: http://stackoverflow.com/questions/9366121/calling-constructor-of-a-generic-type From what I understand, it says that the moment the class is instantiated, the constructor is called, but when a Generic type is inferred in this class, the type so far is unknown, so java has no way to check the type T because until the constructor is finished, this type is unknown.

  • @bigown if your English is good, please check this topic on Soen, by instant translation, seems to answer this case.

  • @Diegofelipe this I had already realized, because if I could, they would, I even wondered what was the reason since they use type Erasure. What I want to know is how to solve this. I imagine is to do what is done in dynamic language. And some people say that Java is a safe language in types, especially when you buy with C#.

  • A light at the end of the tunnel http://stackoverflow.com/questions/1942644/get-generic-type-of-java-util-list/ I just can’t explain why unfortunately I haven’t learned java reflection yet (although this topic is a challenge for such hehe).

Show 11 more comments

2 answers

4


You are creating the instance in the "wrong way"

You are not creating an instance of your class Generic, so the compiler is accepting a different type in the constructor without error.

This way you created an instance of your class:

Grid<Empresa> grid = new Grid(...);

is permitted by the compiler due to backward compatibility. See: The Java Tutorials - Raw Types.

In short, although you have no class Grid for what you declared was Grid<T>, namely, a Generic, compiler considers that there is a yes class Grid and he calls her raw type. It needs this for compatibility with old code, prior to the advent of Generics

However, how to create a class instance Generic is this:

Grid<Empresa> grid = new Grid<Empresa>(...);

new Grid<Company>(...) instead of new Grid(...)

That is, you should inform the Generic Parameter in creating the instance, otherwise you are actually creating an instance of the raw type and not an instance of your Generic class.

If you correctly create an instance of the class Generic you will have a build error when the type passed to your constructor does not match the type of the Generic Parameter.

In C# (another language to support Generics) there’s no such thing as raw type so that you are obliged to explain the Generic Parameter as I did above.

In Java you can also use the syntax called Diamond <>, letting the compiler hint at the type of Generic Parameter from the variable declaration:

Grid<Empresa> grid = new Grid<>(...);

If you follow this practice, explaining the Generic Parameter or using the syntax Diamond, a build error will be generated if you try to use an instance of type incompatible with Generic Parameter informed.

Why Netbeans Warns Against Bad Practice?

Because the Warning compiler regarding the use of raw types is turned off by default. If you look at the hints compiler, however, the warning will be there:

Note: Main.java uses unchecked or unsafe operations.

If you activate this Warning in Netbeans (in Eclipse it is enabled by default), you will be notified by the editor and also during compilation with the following message:

Grid is a raw type. References to generic type Grid 
should be parameterized.
Type safety: The constructor Grid(Integer, List) belongs to the raw type Grid. 
References to generic type Grid should be parameterized.

You could even treat this Warning as an error, preventing compilation when an instance of a raw type.

I don’t have Netbeans installed but this image shows more or less where this setting is:

inserir a descrição da imagem aqui

  • I think that’s right. Instantiating this way and with different types the Netbeans has already "cussed" before compiling...

1

From the research I did it is not possible to resolve this issue at compile time. However the compiler(Eclipse) gives the following Warning:

Type Safety: The Expression of type Grid needs unchecked Conversion to conform to Grid

in the code new Grid(10, listaUsuarios);

This behavior is described in documentation in the following paragraph:

Type Inference and Instantiation of Generic Classes

You can replace the type Arguments required to invoke the constructor of a Generic class with an Empty set of type Parameters (<>) as long as the Compiler can infer the type Arguments from the context. This pair of Angle Brackets is informally called the Diamond.

For example, consider the following variable declaration:

Map<String, List<String>> myMap = new HashMap<String, List<String>>();

You can substitute the parameterized type of the constructor with an Empty set of type Parameters (<>):

Map<String, List<String>> myMap = new HashMap<>();

Note that to take Advantage of type inference During Generic class instantiation, you must use the Diamond. In the following example, the Compiler generates an unchecked Conversion Warning because the Hashmap() constructor refers to the Hashmap raw type, not the Map<String, List<String>> type:

Map<String, List<String>> myMap = new HashMap(); // unchecked conversion warning

Basically it says that the type of arguments required to invoke the constructor of a generic class can be replaced by an empty set of argument types (<>) since the compiler can infer the type through the context.
If types are not indicated or not used <> the compiler will generate a unchecked Conversion Warning

Use Grid<Empresa> grid = new Grid<>(10, listaUsuarios); compiler will generate the following build error:

Cannot infer type Arguments for Grid<>

Explaining with examples:

  • Different types and not used <>

    List<Usuario> listaUsuarios = new ArrayList<>();
    Grid<Empresa> grid = new Grid(10, listaUsuarios);
    

    The compiler generates a Warning:

    Type Safety: The Expression of type Grid needs unchecked Conversion to conform to Grid

  • Different types using <>

    List<Usuario> listaUsuarios = new ArrayList<>();
    Grid<Empresa> grid = new Grid(10, listaUsuarios);
    

    Compiler generates an error:

    Cannot infer type Arguments for Grid<>

  • Equal and unused types <>

    List<Empresa> listaUsuarios = new ArrayList<>();
    Grid<Empresa> grid = new Grid(10, listaUsuarios);
    

    The compiler generates a Warning:

    Type Safety: The Expression of type Grid needs unchecked Conversion to conform to Grid<Empresa>

  • Equal types using <>

    List<Empresa> listaUsuarios = new ArrayList<>();
    Grid<Empresa> grid = new Grid<>(10, listaUsuarios);
    

    The compiler is "content", without error and without Warning.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.