• Watch & Listen
  • Oracle University

Next in the Series: Type Inference

Introducing Generics

Why use generics.

In a nutshell, generics enable types (classes and interfaces) to be parameters when defining classes, interfaces and methods. Much like the more familiar formal parameters used in method declarations, type parameters provide a way for you to re-use the same code with different inputs. The difference is that the inputs to formal parameters are values, while the inputs to type parameters are types.

Code that uses generics has many benefits over non-generic code:

Stronger type checks at compile time. A Java compiler applies strong type checking to generic code and issues errors if the code violates type safety. Fixing compile-time errors is easier than fixing runtime errors, which can be difficult to find.

Elimination of casts. The following code snippet without generics requires casting:

When re-written to use generics, the code does not require casting:

  • Enabling programmers to implement generic algorithms. By using generics, programmers can implement generic algorithms that work on collections of different types, can be customized, and are type safe and easier to read.

Generic Types

A simple box class.

A generic type is a generic class or interface that is parameterized over types. The following Box class will be modified to demonstrate the concept.

Since its methods accept or return an Object , you are free to pass in whatever you want, provided that it is not one of the primitive types. There is no way to verify, at compile time, how the class is used. One part of the code may place an Integer in the box and expect to get objects of type Integer out of it, while another part of the code may mistakenly pass in a String , resulting in a runtime error.

A Generic Version of the Box Class

A generic class is defined with the following format:

The type parameter section, delimited by angle brackets ( <> ), follows the class name. It specifies the type parameters (also called type variables) T1 , T2 , ..., and Tn .

To update the Box class to use generics, you create a generic type declaration by changing the code " public class Box " to " public class Box<T> ". This introduces the type variable, T , that can be used anywhere inside the class.

With this change, the Box class becomes:

As you can see, all occurrences of Object are replaced by T . A type variable can be any non-primitive type you specify: any class type, any interface type, any array type, or even another type variable.

This same technique can be applied to create generic interfaces.

Type Parameter Naming Conventions

By convention, type parameter names are single, uppercase letters. This stands in sharp contrast to the variable naming conventions that you already know about, and with good reason: without this convention, it would be difficult to tell the difference between a type variable and an ordinary class or interface name.

The most commonly used type parameter names are:

E - Element (used extensively by the Java Collections Framework)

S, U, V etc. - 2nd, 3rd, 4th types

You will see these names used throughout the Java SE API and the rest of this section.

Invoking and Instantiating a Generic Type

To reference the generic Box class from within your code, you must perform a generic type invocation, which replaces T with some concrete value, such as Integer :

You can think of a generic type invocation as being similar to an ordinary method invocation, but instead of passing an argument to a method, you are passing a type argument — Integer in this case — to the Box class itself.

Type Parameter and Type Argument Terminology : Many developers use the terms "type parameter" and "type argument" interchangeably, but these terms are not the same. When coding, one provides type arguments in order to create a parameterized type. Therefore, the T in Foo<T> is a type parameter and the String in Foo<String> f is a type argument. This section observes this definition when using these terms.

Like any other variable declaration, this code does not actually create a new Box object. It simply declares that integerBox will hold a reference to a "Box of Integer", which is how Box<Integer> is read.

An invocation of a generic type is generally known as a parameterized type.

To instantiate this class, use the new keyword, as usual, but place <Integer> between the class name and the parenthesis:

The Diamond

In Java SE 7 and later, you can replace the type arguments required to invoke the constructor of a generic class with an empty set of type arguments ( <> ) as long as the compiler can determine, or infer, the type arguments from the context. This pair of angle brackets, <> , is informally called the diamond. For example, you can create an instance of Box<Integer> with the following statement:

For more information on diamond notation and type inference, see the Type Inference section of this tutorial.

Multiple Type Parameters

As mentioned previously, a generic class can have multiple type parameters. For example, the generic OrderedPair class, which implements the generic Pair interface:

The following statements create two instantiations of the OrderedPair class:

The code, new OrderedPair<String, Integer>() , instantiates K as a String and V as an Integer . Therefore, the parameter types of OrderedPair 's constructor are String and Integer , respectively. Due to autoboxing, it is valid to pass a String and an int to the class.

As mentioned in The Diamond section, because a Java compiler can infer the K and V types from the declaration OrderedPair<String, Integer> , these statements can be shortened using diamond notation:

To create a generic interface, follow the same conventions as for creating a generic class.

Parameterized Types

You can also substitute a type parameter (that is, K or V ) with a parameterized type, that is, List<String> . For example, using the OrderedPair<K, V> example:

A raw type is the name of a generic class or interface without any type arguments. For example, given the generic Box class:

To create a parameterized type of Box<T> , you supply an actual type argument for the formal type parameter T :

If the actual type argument is omitted, you create a raw type of Box<T> :

Therefore, Box is the raw type of the generic type Box<T> . However, a non-generic class or interface type is not a raw type.

Raw types show up in legacy code because lots of API classes (such as the Collections classes) were not generic prior to JDK 5.0. When using raw types, you essentially get pre-generics behavior — a Box gives you Objects. For backward compatibility, assigning a parameterized type to its raw type is allowed:

But if you assign a raw type to a parameterized type, you get a warning:

You also get a warning if you use a raw type to invoke generic methods defined in the corresponding generic type:

The warning shows that raw types bypass generic type checks, deferring the catch of unsafe code to runtime. Therefore, you should avoid using raw types.

The Type Erasure section has more information on how the Java compiler uses raw types.

Unchecked Error Messages

As mentioned previously, when mixing legacy code with generic code, you may encounter warning messages similar to the following:

This can happen when using an older API that operates on raw types, as shown in the following example:

The term "unchecked" means that the compiler does not have enough type information to perform all type checks necessary to ensure type safety. The "unchecked" warning is disabled, by default, though the compiler gives a hint. To see all "unchecked" warnings, recompile with -Xlint:unchecked .

Recompiling the previous example with -Xlint:unchecked reveals the following additional information:

To completely disable unchecked warnings, use the -Xlint:-unchecked flag. The @SuppressWarnings("unchecked") annotation suppresses unchecked warnings. If you are unfamiliar with the @SuppressWarnings syntax, see the section Annotations.

Generic Methods

Generic methods are methods that introduce their own type parameters. This is similar to declaring a generic type, but the type parameter's scope is limited to the method where it is declared. Static and non-static generic methods are allowed, as well as generic class constructors.

The syntax for a generic method includes a list of type parameters, inside angle brackets, which appears before the method's return type. For static generic methods, the type parameter section must appear before the method's return type.

The Util class includes a generic method, compare, which compares two Pair objects:

The complete syntax for invoking this method would be:

The type has been explicitly provided, as shown in bold. Generally, this can be left out and the compiler will infer the type that is needed:

This feature, known as type inference, allows you to invoke a generic method as an ordinary method, without specifying a type between angle brackets. This topic is further discussed in the following section, Type Inference.

Bounded Type Parameters

There may be times when you want to restrict the types that can be used as type arguments in a parameterized type. For example, a method that operates on numbers might only want to accept instances of Number or its subclasses. This is what bounded type parameters are for.

To declare a bounded type parameter, list the type parameter's name, followed by the extends keyword, followed by its upper bound, which in this example is Number . Note that, in this context, extends is used in a general sense to mean either " extends " (as in classes) or " implements " (as in interfaces).

By modifying our generic method to include this bounded type parameter, compilation will now fail, since our invocation of inspect still includes a String :

In addition to limiting the types you can use to instantiate a generic type, bounded type parameters allow you to invoke methods defined in the bounds:

The isEven() method invokes the intValue() method defined in the Integer class through n .

Multiple Bounds

The preceding example illustrates the use of a type parameter with a single bound, but a type parameter can have multiple bounds:

A type variable with multiple bounds is a subtype of all the types listed in the bound. If one of the bounds is a class, it must be specified first. For example:

If bound A is not specified first, you get a compile-time error:

Generic Methods and Bounded Type Parameters

Bounded type parameters are key to the implementation of generic algorithms. Consider the following method that counts the number of elements in an array T[] that are greater than a specified element elem .

The implementation of the method is straightforward, but it does not compile because the greater than operator ( > ) applies only to primitive types such as short , int , double , long , float , byte , and char . You cannot use the > operator to compare objects. To fix the problem, use a type parameter bounded by the Comparable<T> interface:

The resulting code will be:

Generics, Inheritance, and Subtypes

As you already know, it is possible to assign an object of one type to an object of another type provided that the types are compatible. For example, you can assign an Integer to an Object , since Object is one of Integer 's supertypes:

In object-oriented terminology, this is called an "is a" relationship. Since an Integer is a kind of Object, the assignment is allowed. But Integer is also a kind of Number , so the following code is valid as well:

The same is also true with generics. You can perform a generic type invocation, passing Number as its type argument, and any subsequent invocation of add will be allowed if the argument is compatible with Number :

Now consider the following method:

What type of argument does it accept? By looking at its signature, you can see that it accepts a single argument whose type is Box<Number> . But what does that mean? Are you allowed to pass in Box<Integer> or Box<Double> , as you might expect? The answer is "no", because Box<Integer> and Box<Double> are not subtypes of Box<Number> .

This is a common misunderstanding when it comes to programming with generics, but it is an important concept to learn. Box<Integer> is not a subtype of Box<Number> even though Integer is a subtype of Number .

Subtyping parameterized types

Note: Given two concrete types A and B , for example, Number and Integer , MyClass<A> has no relationship to MyClass<B> , regardless of whether or not A and B are related. The common parent of MyClass<A> and MyClass<B> is Object .

For information on how to create a subtype-like relationship between two generic classes when the type parameters are related, see the section Wildcards and Subtyping .

Generic Classes and Subtyping

You can subtype a generic class or interface by extending or implementing it. The relationship between the type parameters of one class or interface and the type parameters of another are determined by the extends and implements clauses.

Using the Collections classes as an example, ArrayList<E> implements List<E> , and List<E> extends Collection<E> . So ArrayList<String> is a subtype of List<String> , which is a subtype of Collection<String> . So long as you do not vary the type argument, the subtyping relationship is preserved between the types.

A sample Collection hierarchy

Now imagine we want to define our own list interface, PayloadList , that associates an optional value of generic type P with each element. Its declaration might look like:

The following parameterizations of PayloadList are subtypes of List<String> :

  • PayloadList<String,String>
  • PayloadList<String,Integer>
  • PayloadList<String,Exception>

A sample Payload hierarchy

In this tutorial

Last update: September 14, 2021

DEV Community

DEV Community

Emil Ossola

Posted on Jun 1, 2023

How to Avoid Unchecked Casts in Java Programs

Unchecked cast refers to the process of converting a variable of one data type to another data type without checks by the Java compiler.

This operation is unchecked because the compiler does not verify if the operation is valid or safe. Unchecked casts can lead to runtime errors, such as ClassCastException, when the program tries to assign an object to a variable of an incompatible type.

Hence, it is important to avoid unchecked casts in Java programs to prevent potential errors and ensure the program's reliability.

Image description

Consequences of Unchecked Casts

In Java programs, unchecked casts can lead to several issues. The most common problem is a ClassCastException at runtime, which occurs when we try to cast an object to a wrong type. This can cause the program to crash or behave unexpectedly.

Unchecked casts also violate the type safety of the Java language, which can lead to bugs that are difficult to detect and debug. Additionally, unchecked casts can make the code less readable and maintainable, as they hide the true type of objects and dependencies between components.

Therefore, it is important to avoid unchecked casts and use other mechanisms, such as generics or polymorphism, to ensure type safety and code quality in Java programs.

Image description

How Unchecked Casts Occur

Unchecked casts in Java programs occur when an object of one type is assigned to a reference of another type without proper type checking. This can happen when a programmer assumes that a reference to a superclass is actually a reference to its subclass and tries to cast it into that subclass. If the assumption is incorrect, the cast will result in a ClassCastException at runtime.

Unchecked casts can also occur when dealing with raw types, which are generic types without any type parameters specified. In such cases, the compiler cannot perform type checking and the programmer must ensure that the proper type conversions are made. Failing to do so can result in unchecked casts and potential runtime errors.

Why unchecked casts are problematic

In Java, unchecked casts allow a programmer to cast any object reference to any other reference type without providing any type information at compile-time. While this flexibility may seem useful, it can lead to serious run-time errors. If the object being casted is not actually of the type specified, a ClassCastException will occur at run-time.

Unchecked casts can cause difficult-to-debug errors in large and complex codebases, as it may not be immediately clear where the error originated. Additionally, unchecked casts can undermine Java's type system, creating code that is harder to read, maintain, and reason about. As a result, avoiding unchecked casts should be a priority when writing Java programs.

Examples of Unchecked Casts in Java

Unchecked casts are a common source of Java program errors. Here are some examples of unchecked casts:

This cast statement above can result in a class cast exception if the object referred to by obj is not a List.

In this case, the cast could fail at runtime if the array contains objects of a type other than String.

Finally, this cast could fail if the object referred to by obj is not a Map.

Using Generics to Avoid Unchecked Casts in Java

In Java, Generics is a powerful feature that allows you to write classes and methods that are parameterized by one or more types. Generics are a way of making your code more type-safe and reusable. With generics, you can define classes and methods that work on a variety of types, without having to write separate code for each type.

Using generics in Java programs has several advantages. It enables type safety at compile-time, which can prevent ClassCastException errors at runtime. With generics, the compiler can detect type mismatches and prevent them from happening, which leads to more robust and reliable code. It also allows for code reuse without sacrificing type safety and improve performance by avoiding unnecessary casting and allowing for more efficient code generation.

Generics allow Java developers to create classes and methods that can work with different data types. For example, a List can be defined to hold any type of object using generics. Here's an example:

In this example, we create a List that holds String objects. We can add String objects to the list and iterate over them using a for-each loop. The use of generics allows us to ensure type safety and avoid unchecked casts. Another example is the Map interface, which can be used to map keys to values of any data type using generics.

Using the instanceof operator to Avoid Unchecked Casts in Java

The instanceof operator is a built-in operator in Java that is used to check whether an object is an instance of a particular class or interface. The operator returns a boolean value - true if the object is an instance of the specified class or interface, and false otherwise.

The instanceof operator is defined as follows:

where object is the object that is being checked, and class/interface is the class or interface that is being tested against.

The instanceof operator can be useful in situations where we need to perform different operations based on the type of an object. It provides a way to check the type of an object at runtime, which can help prevent errors that can occur when performing unchecked casts.

Here are some examples of using the instanceof operator:

In this example, we use the instanceof operator to check whether the object obj is an instance of the String class. If it is, we perform an explicit cast to convert the object to a String and call the toUpperCase() method on it.

In this example, we use the instanceof operator to check whether the List object passed as a parameter is an instance of the ArrayList or LinkedList classes. If it is, we perform an explicit cast to convert the List to the appropriate class and perform different operations on it depending on its type.

Overall, using the instanceof operator can help us write more robust and flexible code. However, it should be used judiciously as it can also make code harder to read and understand.

Using Polymorphism to Avoid Unchecked Casts in Java

Polymorphism is a fundamental concept in object-oriented programming. It refers to the ability of an object or method to take on multiple forms. It allows us to write code that can work with objects of different classes as long as they inherit from a common superclass or implement a common interface. This helps to reduce code duplication and makes our programs more modular and extensible.

Some of the advantages of using polymorphism are:

  • Code reusability: We can write code that can work with multiple objects without having to rewrite it for each specific class.
  • Flexibility: Polymorphism allows us to write code that can adapt to different types of objects at runtime.
  • Ease of maintenance: By using polymorphism, changes made to a superclass or interface are automatically propagated to all its subclasses.

Here are a few examples of how you can use polymorphism to avoid unchecked casts in Java:

Example 1: Shape Hierarchy

In this example, the abstract class Shape defines the common behavior draw(), which is implemented by the concrete classes Circle and Rectangle. By using the Shape reference type, we can invoke the draw() method on different objects without the need for unchecked casts.

Example 2: Polymorphic Method Parameter

In this example, the makeAnimalSound() method accepts an Animal parameter. We can pass different Animal objects, such as Dog or Cat, without the need for unchecked casts. The appropriate implementation of the makeSound() method will be invoked based on the dynamic type of the object.

By utilizing polymorphism in these examples, we achieve type safety and avoid unchecked casts, allowing for cleaner and more flexible code.

Tips to Avoid Unchecked Casts in Java Programs

Unchecked casts in Java programs can introduce runtime errors and compromise type safety. Fortunately, there are several techniques and best practices you can employ to avoid unchecked casts and ensure a more robust codebase. Here are some effective tips to help you write Java programs that are type-safe and free from unchecked cast exceptions.

  • Use generic classes, interfaces, and methods to ensure that your code handles compatible types without relying on casting.
  • Embrace polymorphism by utilizing abstract classes and interfaces, define common behavior and interact with objects through their common type.
  • Check the type of an object using the instanceof operator. This allows you to verify that an object is of the expected type before proceeding with the cast.
  • Favor composition over inheritance, where classes contain references to other classes as instance variables.
  • Familiarize yourself with design patterns that promote type safety and avoid unchecked casts. Patterns such as Factory Method, Builder, and Strategy provide alternative approaches to object creation and behavior, often eliminating the need for explicit casting.
  • Clearly define the contracts and preconditions for your methods. A well-defined contract helps ensure that the method is called with appropriate types, improving overall code safety.
  • Refactor your code and improve its overall design. Look for opportunities to apply the aforementioned tips, such as utilizing generics, polymorphism, or design patterns.

Unchecked casts in Java programs can introduce runtime errors and undermine type safety. By adopting practices like using generics, leveraging polymorphism, checking types with instanceof, favoring composition over inheritance, reviewing design patterns, employing design by contract, and improving code design, you can avoid unchecked casts and enhance the robustness of your Java programs. Prioritizing type safety will result in more reliable code and a smoother development process.

Lightly IDE as a Programming Learning Platform

So, you want to learn a new programming language? Don't worry, it's not like climbing Mount Everest. With Lightly IDE, you'll feel like a coding pro in no time. With Lightly IDE , you don't need to be a coding wizard to start programming.

Uploading image

One of its standout features is its intuitive design, which makes it easy to use even if you're a technologically challenged unicorn. With just a few clicks, you can become a programming wizard in Lightly IDE. It's like magic, but with less wands and more code.

If you're looking to dip your toes into the world of programming or just want to pretend like you know what you're doing, Lightly IDE's online Java compiler is the perfect place to start. It's like a playground for programming geniuses in the making! Even if you're a total newbie, this platform will make you feel like a coding superstar in no time.

Read more: How to Avoid Unchecked Casts in Java Programs

Top comments (0)

pic

Templates let you quickly answer FAQs or store snippets for re-use.

Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment's permalink .

Hide child comments as well

For further actions, you may consider blocking this person and/or reporting abuse

franckpachot profile image

Optimizing Fuzzy Search Across Multiple Tables: pg_trgm, GIN, and Triggers

Franck Pachot - Jul 4

samirfcis profile image

Revamped Mock-API.net: Simplifying API Mocking for Developers

Samir - Jul 4

khalidelgazzar profile image

تعزيز موقع الويب الخاص بك: واجهة أمامية و خلفية بدون خادم باستخدام 8 خدمات من أيه دبليو إس

Khalid ElGazzar - Jul 4

chrisarg profile image

How can we get and set the OpenMP environment from Perl?

chrisarg - Jul 4

DEV Community

We're a place where coders share, stay up-to-date and grow their careers.

Guide to Understanding Generics in Java

java generics unchecked assignment

  • Introduction

Java is a type-safe programming language. Type safety ensures a layer of validity and robustness in a programming language. It is a key part of Java's security to ensure that operations done on an object are only performed if the type of the object supports it.

Type safety dramatically reduces the number of programming errors that might occur during runtime, involving all kinds of errors linked to type mismatches. Instead, these types of errors are caught during compile-time which is much better than catching errors during runtime, allowing developers to have less unexpected and unplanned trips to the good old debugger.

Type safety is also interchangeably called strong typing .

Java Generics is a solution designed to reinforce the type safety that Java was designed to have. Generics allow types to be parameterized onto methods and classes and introduces a new layer of abstraction for formal parameters . This will be explained in detail later on.

There are many advantages of using generics in Java. Implementing generics into your code can greatly improve its overall quality by preventing unprecedented runtime errors involving data types and typecasting.

This guide will demonstrate the declaration, implementation, use-cases, and benefits of generics in Java.
  • Why Use Generics?

To provide context as to how generics reinforce strong typing and prevent runtime errors involving typecasting, let's take a look at a code snippet.

Let's say you want to store a bunch of String variables in a list. Coding this without using generics would look like this:

This code won't trigger any compile-time errors but most IDEs will warn you that the List that you've initialized is of a raw type and should be parameterized with a generic.

IDE-s warn you of problems that can occur if you don't parameterize a list with a type. One is being able to add elements of any data type to the list. Lists will, by default, accept any Object type, which includes every single one of its subtypes:

Adding two or more different types within the same collection violates the rules of type safety. This code will successfully compile but this definitely will cause a multitude of problems.

For example, what happens if we try to loop through the list? Let's use an enhanced for loop:

We'll be greeted with a:

In fact, this isn't because we've put a String and Integer together. If we changed the example around and added two String s:

We'd still be greeted with:

This is because without any parametrization, the List only deals with Object s. You can technically circumvent this by using an Object in the enhanced for-loop:

Which would print out:

However, this is very much against intuition and isn't a real fix. This is just avoiding the underlying design problem in an unsustainable way.

Another problem is the need to typecast whenever you access and assign elements within a list without generics. To assign new reference variables to the elements of the list, we must typecast them, since the get() method returns Object s:

In this case, how will you be able to determine the type of each element during runtime, so you know which type to cast it to? There aren't many options and the ones at your disposal complicate things way out of proportion, like using try / catch blocks to try and cast elements into some predefined types.

Also, if you fail to cast the list element during assignment, it will display an error like this:

In OOP, explicit casting should be avoided as much as possible because it isn't a reliable solution for OOP-related problems.

Lastly, because the List class is a subtype of Collection , it should have access to iterators using the Iterator object, the iterator() method, and for-each loops. If a collection is declared without generics, then you definitely won't be able to use any of these iterators, in a reasonable manner.

This is why Java Generics came to be, and why they're an integral part of the Java ecosystem. Let's take a look at how to declare generic classes, and rewrite this example to utilize generics and avoid the issues we've just seen.

  • Generic Classes and Objects

Let's declare a class with a generic type. To specify a parameter type on a class or an object, we use the angle bracket symbols <> beside its name and assign a type for it inside the brackets. The syntax of declaring a generic class looks like this:

Note: Generic types can NOT be assigned primitive data types such as int , char , long , double , or float . If you want to assign these data types, then use their wrapper classes instead.

The letter T inside the angle brackets is called a type parameter . By convention, type parameters are single lettered (A-Z) and uppercase. Some other common type parameter names used are K (Key), V (Value), E (Element), and N (Number).

Although you can, in theory, assign any variable name to a type parameter that follows Java's variable conventions, it is with good reason to follow the typical type parameter convention to differentiate a normal variable from a type parameter.

The val is of a generic type. It can be a String , an Integer , or another object. Given the generic class Thing declared above, let's instantiate the class as a few different objects, of different types:

Notice how we're not specifying the parameter type before the constructor calls. Java infers the type of the object during initialization so you won't need to retype it during the initialization. In this case, the type is already inferred from the variable declaration. This behavior is called type inference . If we inherited this class, in a class such as SubThing , we also wouldn't need to explicitly set the type when instantiating it as a Thing , since it'd infer the type from its parent class.

You can specify it in both places, but it's just redundant:

If we run the code, it'll result in:

Using generics allows type-safe abstraction without having to use type casting which is much riskier in the long run.

In a similar vein, the List constructor accepts a generic type:

In our previous examples, we haven't specified a type, resulting in the List being a List of Object s. Now, let's rewrite the example from before:

This results in:

Works like a charm! Again, we don't need to specify the type in the ArrayList() call, since it infers the type from the List<String> definition. The only case in which you'll have to specify the type after the constructor call is if you're taking advantage of the local variable type inference feature of Java 10+:

This time around, since we're using the var keyword, which isn't type-safe itself, the ArrayList<>() call can't infer the type, and it'll simply default to an Object type if we don't specify it ourselves.

  • Generic Methods

Java supports method declarations with generic parameters and return types. Generic methods are declared exactly like normal methods but have the angle brackets notation before the return type.

Let's declare a simple generic method that accepts 3 parameters, appends them in a list, and return it:

Now, we can run this as:

Which results in:

But also, we can throw in other types:

Multiple types of parameters are also supported for objects and methods. If a method uses more than one type parameter, you can provide a list of all of them inside the diamond operator and separate each parameter using commas:

Here, you can get creative with what you pass in. Following the conventions, we'll pass in a type, key and value:

Though, keep in mind that generic type parameters, that can be inferred, don't need to be declared in the generic declaration before the return type. To demonstrate, let's create another method that accepts 2 variables - a generic Map and a List that can exclusively contain String values:

Check out our hands-on, practical guide to learning Git, with best-practices, industry-accepted standards, and included cheat sheet. Stop Googling Git commands and actually learn it!

Here, the K and V generic types are mapped to the Map<K, V> since they're inferred types. On the other hand, since the List<String> can only accept strings, there's no need to add the generic type to the <K, V> list.

We've now covered generic classes, objects, and methods with one or more type parameters. What if we want to limit the extent of abstraction that a type parameter has? This limitation can be implemented using parameter binding.

  • Bounded Type Parameters

Parameter Binding allows the type parameter to be limited to an object and its subclasses. This allows you to enforce certain classes and their subtypes, while still having the flexibility and abstraction of using generic type parameters.

To specify that a type parameter is bounded, we simply use the extends keyword on the type parameter - <N extends Number> . This makes sure that the type parameter N we supply to a class or method is of type Number .

Let's declare a class, called InvoiceDetail , which accepts a type parameter, and make sure that that type parameter is of type Number . This way, the generic types we can use while instantiating the class are limited to numbers and floating-point decimals, as Number is the superclass of all classes involving integers, including the wrapper classes and primitive data types:

Here, extends can mean two things - extends , in the case of classes, and implements in the case of interfaces. Since Number is an abstract class, it's used in the context of extending that class.

By extending the type parameter N as a Number subclass, the instantiation of amount and discount are now limited to Number and its subtypes. Trying to set them to any other type will trigger a compile-time error.

Let's try to erroneously assign String values, instead of a Number type:

Since String isn't a subtype of Number , the compiler catches that and triggers an error:

This is a great example of how using generics enforces type-safety.

Additionally, a single type parameter can extend multiple classes and interfaces by using the & operator for the subsequently extended classes:

It's also worth noting that another great usage of bounded type parameters is in method declarations. For example, if you want to enforce that the types passed into a method conform to some interfaces, you can make sure that the type parameters extend a certain interface.

A classic example of this is enforcing that two types are Comparable , if you're comparing them in a method such as:

Here, using generics, we enforce that t1 and t2 are both Comparable , and that they can genuinely be compared with the compareTo() method. Knowing that String s are comparable, and override the compareTo() method, we can comfortably use them here:

The code results in:

However, if we tried using a non- Comparable type, such as Thing , which doesn't implement the Comparable interface:

Other than the IDE marking this line as erroneous, if we try running this code, it'll result in:

In this case, since Comparable is an interface, the extends keyword actually enforces that the interface is implemented by T , not extended.

  • Wildcards in Generics

Wildcards are used to symbolize any class type, and are denoted by ? . In general, you'll want to use wildcards when you have potential incompatibilities between different instantiations of a generic type. There are three types of wildcards: upper-bounded , lower-bounded and unbounded .

Choosing which approach you'll use is usually determined by the IN-OUT principle. The IN-OUT principle defines In-variables and Out-variables , which, in simpler terms, represent if a variable is used to provide data, or to serve in its output.

For example, a sendEmail(String body, String recipient) method has an In-variable body and Out-variable recipient . The body variable provides data on the body of the email you'd like to send, while the recipient variable provides the email address you'd like to send it to.

There are also mixed variables , which are used to both provide data, and then reference the result itself, in which case, you'll want to avoid using wildcards .

Generally speaking, you'll want to define In-variables with upper bounded wildcards, using the extends keyword and Out-variables with lower bounded wildcards, using the super keyword.

For In-variables that can be accessed through the method of an object, you should prefer unbounded wildcards.

  • Upper-Bounded Wildcards

Upper-bound wildcards are used to provide a generic type that limits a variable to a class or an interface and all its subtypes . The name, upper-bounded refers to the fact that you bound the variable to an upper type - and all of its subtypes.

In a sense, upper-bounded variables are more relaxed than lower-bounded variables, since they allow for more types. They're declared using the wildcard operator ? followed by the keyword extends and the supertype class or interface (the upper bound of their type):

Here, extends , again, means extends classes and implements interfaces.

To recap, upper-bounded wildcards are typically used for objects that provide input to be consumed in-variables.

Note: There's a distinct difference between Class<Generic> and Class<? extends Generic> . The former allows only the Generic type to be used. In the latter, all subtypes of Generic are also valid.

Let's make an upper-type ( Employee ) and its subclass ( Developer ):

Now, let's make a simple printInfo() method, that accepts an upper-bounded list of Employee objects:

The List of employees we supply is upper-bounded to Employee , which means we can chuck in any Employee instance, as well as its subclasses, such as Developer :

  • Lower-Bounded Wildcards

Lower-bounded wildcards are the opposite of upper-bounded. This allows a generic type to be restricted to a class or interface and all its supertypes . Here, the class or interface is the lower bound :

Subtypes and Supertypes

Declaring lower-bounded wildcards follows the same pattern as upper-bounded wildcards - a wildcard ( ? ) followed by super and the supertype:

Based on the IN-OUT principle, lower-bounded wildcards are used for objects that are involved in the output of data. These objects are called out variables.

Let's revisit the email functionality from before and make a hierarchy of classes:

Now, let's make a subclass for Email :

We'll also want to have some utility class, such as MailSender to "send" emails and notify us of the results:

Finally, let's write a method that accepts a body and recipients list and sends them the body, notifying us of the result:

Here, we've used a lower-bounded generic type of ValidEmail , which extends Email . So, we're free to create Email instances, and chuck them into this method:

  • Unbounded Wildcards

Unbounded wildcards are wildcards without any form of binding. Simply put, they are wildcards that extend every single class starting from the base Object class.

Unbounded wildcards are used when the Object class is the one being accessed or manipulated or if the method it's being used on does not access or manipulate using a type parameter. Otherwise, using unbounded wildcards will compromise the type safety of the method.

To declare an unbounded wildcard, simply use the question mark operator encapsulated within angle brackets <?> .

For example, we can have a List of any element:

System.out.println() accepts any object, so we're good to go here. If the method were to copy an existing list into a new list, then upper-bounded wildcards are more favorable.

  • Difference Between Bounded Wildcards and Bounded Type Parameters?

You may have noticed the sections for bounded wildcards and bounded type parameters are separated but more or less have the same definition, and on the surface level look like they're interchangeable:

So, what's the difference between these two approaches? There are several differences, in fact:

  • Bounded type parameters accept multiple extends using the & keyword while bounded wildcards only accept one single type to extend.
  • Bounded type parameters are only limited to upper-bounds. This means that you cannot use the super keyword on bounded type parameters.
  • class Example<? extends Object> {...}
  • GenericObj<?> = new GenericObj<?>()
  • GenericObj<? extends Object> = new GenericObj<? extends Object>()
  • Bounded wildcards should not be used as return types. This will not trigger any errors or exceptions but it forces unnecessary handling and typecasting which is completely against the type safety that generics achieves.
  • public <?> void printDisplay(? var) {} will fail during compilation, while
  • public <E> void printDisplay(E var) compiles and runs successfully.
  • Benefits of Using Generics

Throughout the guide, we've covered the primary benefit of generics - to provide an additional layer of type safety for your program. Apart from that, generics offer many other benefits over code that doesn't use them.

  • Runtime errors involving types and casting are caught during compile time. The reason why typecasting should be avoided is that the compiler does not recognize casting exceptions during compile time. When used correctly, generics completely avoids the use of typecasting and subsequently avoids all the runtime exceptions that it might trigger.
  • Classes and methods are more reusable. With generics, classes and methods can be reused by different types without having to override methods or create a separate class.

Applying generics to your code will significantly improve code reusability, readability, and more importantly, type safety. In this guide, we've gone into what generics are, how you can apply them, the differences between approaches and when to choose which.

You might also like...

  • Java: Finding Duplicate Elements in a Stream
  • Spring Boot with Redis: HashOperations CRUD Functionality
  • Spring Cloud: Hystrix
  • Java Regular Expressions - How to Validate Emails

Improve your dev skills!

Get tutorials, guides, and dev jobs in your inbox.

No spam ever. Unsubscribe at any time. Read our Privacy Policy.

In this article

java generics unchecked assignment

Monitor with Ping Bot

Reliable monitoring for your app, databases, infrastructure, and the vendors they rely on. Ping Bot is a powerful uptime and performance monitoring tool that helps notify you and resolve issues before they affect your customers.

OpenAI

Vendor Alerts with Ping Bot

Get detailed incident alerts about the status of your favorite vendors. Don't learn about downtime from your customers, be the first to know with Ping Bot.

Supabase

© 2013- 2024 Stack Abuse. All rights reserved.

  • Java Arrays
  • Java Strings
  • Java Collection
  • Java 8 Tutorial
  • Java Multithreading
  • Java Exception Handling
  • Java Programs
  • Java Project
  • Java Collections Interview
  • Java Interview Questions
  • Spring Boot

Generics in Java

Generics means parameterized types . The idea is to allow type (Integer, String, … etc., and user-defined types) to be a parameter to methods, classes, and interfaces. Using Generics, it is possible to create classes that work with different data types. An entity such as class, interface, or method that operates on a parameterized type is a generic entity.

Why Generics?

The Object is the superclass of all other classes, and Object reference can refer to any object. These features lack type safety. Generics add that type of safety feature. We will discuss that type of safety feature in later examples.

Generics in Java are similar to templates in C++. For example, classes like HashSet, ArrayList, HashMap, etc., use generics very well. There are some fundamental differences between the two approaches to generic types. 

Types of Java Generics

Generic Method: Generic Java method takes a parameter and returns some value after performing a task. It is exactly like a normal function, however, a generic method has type parameters that are cited by actual type. This allows the generic method to be used in a more general way. The compiler takes care of the type of safety which enables programmers to code easily since they do not have to perform long, individual type castings.

Generic Classes: A generic class is implemented exactly like a non-generic class. The only difference is that it contains a type parameter section. There can be more than one type of parameter, separated by a comma. The classes, which accept one or more parameters, ?are known as parameterized classes or parameterized types.

Generic Class 

Like C++, we use <> to specify parameter types in generic class creation. To create objects of a generic class, we use the following syntax. 

Note: In Parameter type we can not use primitives like ‘int’,’char’ or ‘double’.

We can also pass multiple Type parameters in Generic classes. 

Generic Functions: 

We can also write generic functions that can be called with different types of arguments based on the type of arguments passed to the generic method. The compiler handles each method.

Generics Work Only with Reference Types: 

When we declare an instance of a generic type, the type argument passed to the type parameter must be a reference type. We cannot use primitive data types like int , char.

The above line results in a compile-time error that can be resolved using type wrappers to encapsulate a primitive type. 

But primitive type arrays can be passed to the type parameter because arrays are reference types.

Generic Types Differ Based on Their Type Arguments: 

Consider the following Java code.

Output:  

Even though iObj and sObj are of type Test, they are the references to different types because their type parameters differ. Generics add type safety through this and prevent errors.

Type Parameters in Java Generics

The type parameters naming conventions are important to learn generics thoroughly. The common type parameters are as follows:

  • T – Type
  • E – Element
  • K – Key
  • N – Number
  • V – Value

Advantages of Generics: 

Programs that use Generics has got many benefits over non-generic code. 

1. Code Reuse: We can write a method/class/interface once and use it for any type we want.

2. Type Safety: Generics make errors to appear compile time than at run time (It’s always better to know problems in your code at compile time rather than making your code fail at run time). Suppose you want to create an ArrayList that store name of students, and if by mistake the programmer adds an integer object instead of a string, the compiler allows it. But, when we retrieve this data from ArrayList, it causes problems at runtime.

How do Generics Solve this Problem? 

When defining ArrayList, we can specify that this list can take only String objects.

3. Individual Type Casting is not needed: If we do not use generics, then, in the above example, every time we retrieve data from ArrayList, we have to typecast it. Typecasting at every retrieval operation is a big headache. If we already know that our list only holds string data, we need not typecast it every time.

4. Generics Promotes Code Reusability: With the help of generics in Java, we can write code that will work with different types of data. For example,

Let’s say we want to Sort the array elements of various data types like int, char, String etc.

Basically we will be needing different functions for different data types.

For simplicity, we will be using Bubble sort.

But by using Generics, we can achieve the code reusability feature.

         

Here, we have created a generics method. This same method can be used to perform operations on integer data, string data, and so on.

5. Implementing Generic Algorithms: By using generics, we can implement algorithms that work on different types of objects, and at the same, they are type-safe too.

Please Login to comment...

Similar reads.

  • Java-Generics

Improve your Coding Skills with Practice

 alt=

What kind of Experience do you want to share?

Generics unchecked assignment

Report post to moderator

SCJP 1.4 - SCJP 6 - SCWCD 5 - OCEEJBD 6 - OCEJPAD 6 How To Ask Questions How To Answer Questions

Consider Paul's .

Creating a Generic Array in Java

Last updated: January 8, 2024

java generics unchecked assignment

Azure Container Apps is a fully managed serverless container service that enables you to build and deploy modern, cloud-native Java applications and microservices at scale. It offers a simplified developer experience while providing the flexibility and portability of containers.

Of course, Azure Container Apps has really solid support for our ecosystem, from a number of build options, managed Java components, native metrics, dynamic logger, and quite a bit more.

To learn more about Java features on Azure Container Apps, you can get started over on the documentation page .

And, you can also ask questions and leave feedback on the Azure Container Apps GitHub page .

Get non-trivial analysis (and trivial, too!) suggested right inside your IDE or Git platform so you can code smart, create more value, and stay confident when you push.

Get CodiumAI for free and become part of a community of over 280,000 developers who are already experiencing improved and quicker coding.

Write code that works the way you meant it to:

>> CodiumAI. Meaningful Code Tests for Busy Devs

DbSchema is a super-flexible database designer, which can take you from designing the DB with your team all the way to safely deploying the schema .

The way it does all of that is by using a design model , a database-independent image of the schema, which can be shared in a team using GIT and compared or deployed on to any database.

And, of course, it can be heavily visual, allowing you to interact with the database using diagrams, visually compose queries, explore the data, generate random data, import data or build HTML5 database reports.

>> Take a look at DBSchema

Slow MySQL query performance is all too common. Of course it is. A good way to go is, naturally, a dedicated profiler that actually understands the ins and outs of MySQL.

The Jet Profiler was built for MySQL only , so it can do things like real-time query performance, focus on most used tables or most frequent queries, quickly identify performance issues and basically help you optimize your queries.

Critically, it has very minimal impact on your server's performance, with most of the profiling work done separately - so it needs no server changes, agents or separate services.

Basically, you install the desktop application, connect to your MySQL server , hit the record button, and you'll have results within minutes:

>> Try out the Profiler

A quick guide to materially improve your tests with Junit 5:

Do JSON right with Jackson

Download the E-book

Get the most out of the Apache HTTP Client

Get Started with Apache Maven:

Working on getting your persistence layer right with Spring?

Explore the eBook

Building a REST API with Spring?

Explore Spring Boot 3 and Spring 6 in-depth through building a full REST API with the framework:

>> REST With Spring (new)

Get started with Spring and Spring Boot, through the reference Learn Spring course:

>> LEARN SPRING

Looking for the ideal Linux distro for running modern Spring apps in the cloud?

Meet Alpaquita Linux : lightweight, secure, and powerful enough to handle heavy workloads.

This distro is specifically designed for running Java apps . It builds upon Alpine and features significant enhancements to excel in high-density container environments while meeting enterprise-grade security standards.

Specifically, the container image size is ~30% smaller than standard options, and it consumes up to 30% less RAM:

>> Try Alpaquita Containers now.

Yes, Spring Security can be complex, from the more advanced functionality within the Core to the deep OAuth support in the framework.

I built the security material as two full courses - Core and OAuth , to get practical with these more complex scenarios. We explore when and how to use each feature and code through it on the backing project .

You can explore the course here:

>> Learn Spring Security

Spring Data JPA is a great way to handle the complexity of JPA with the powerful simplicity of Spring Boot .

Get started with Spring Data JPA through the guided reference course:

>> CHECK OUT THE COURSE

Get started with Spring Boot and with core Spring, through the Learn Spring course:

1. Introduction

We may wish to use arrays as part of classes or functions that support generics , but due to the way Java handles generics, this can be difficult.

In this tutorial, we’ll discuss the challenges of using generics with arrays. Then we’ll create an example of a generic array.

Finally, we’ll see how the Java API has solved a similar problem.

2. Considerations When Using Generic Arrays

An important difference between arrays and generics is how they enforce type checking. Specifically, arrays store and check type information at runtime. Generics, however, check for type errors at compile-time and don’t have type information at runtime.

Java’s syntax suggests we might be able to create a new generic array:

But if we attempted this, we’d get a compile error.

To understand why, let’s consider the following:

As an unbound generic type  T resolves to  Object,  our method at runtime will be:

If we call our method and store the result in a String array:

The code will compile fine, but fail at runtime with a ClassCastException . This is because we just assigned an Object[] to a String[] reference. Specifically, an implicit cast by the compiler will fail to convert Object[] to our required type  String[] .

Although we can’t initialize generic arrays directly, it’s still possible to achieve the equivalent operation if the precise type of information is provided by the calling code.

3. Creating a Generic Array

For our example, let’s consider a bounded stack data structure, MyStack , where the capacity is fixed to a certain size. As we’d like the stack to work with any type, a reasonable implementation choice would be a generic array.

First, we’ll create a field to store the elements of our stack, which is a generic array of type E :

Then we’ll add a constructor:

Notice how we use java.lang.reflect.Array#newInstance to initialize our generic array , which requires two parameters. The first parameter specifies the type of object inside the new array. The second parameter specifies how much space to create for the array. As the result of Array#newInstance  is of type Object , we need to cast it to E[] to create our generic array.

We should also note the convention of naming a type parameter  clazz, rather than  class, which is a reserved word in Java.

4. Considering ArrayList

4.1. using arraylist in place of an array.

It’s often easier to use a generic  ArrayList  in place of a generic array. Let’s see how we can change MyStack to use an ArrayList .

First, we’ll create a field to store our elements:

Then, in our stack constructor, we can initialize the ArrayList with an initial capacity:

It makes our class simpler, as we don’t have to use reflection. Also, we aren’t required to pass in a class literal when creating our stack. As we can set the initial capacity of an ArrayList , we can get the same benefits as an array.

Therefore, we only need to construct arrays of generics in rare situations or when we’re interfacing with some external library that requires an array.

4.2.  ArrayList Implementation

Interestingly, ArrayList itself is implemented using generic arrays. Let’s peek inside ArrayList to see how.

First, let’s see the list elements field:

Notice  ArrayList  uses Object as the element type. As our generic type isn’t known until runtime, Object is used as the superclass of any type.

It’s worth noting that nearly all the operations in ArrayList can use this generic array, as they don’t need to provide a strongly typed array to the outside world (except for one method, toArray).

5. Building an Array From a Collection

5.1. linkedlist example.

Let’s look at using generic arrays in the Java Collections API, where we’ll build a new array from a collection.

First, we’ll create a new LinkedList  with a type argument  String,  and add items to it:

Then we’ll build an array of the items we just added:

To build our array, the List . toArray method requires an input array. It uses this array purely to get the type information to create a return array of the right type.

In our example above, we used new String[0] as our input array to build the resulting String array.

5.2.  LinkedList.toArray Implementation

Let’s take a peek inside  LinkedList.toArray  to see how it’s implemented in the Java JDK.

First, we’ll look at the method signature:

Then we’ll see how a new array is created when required:

Notice how it makes use of  Array#newInstance to build a new array, like in our previous stack example. We can also see that parameter a is used to provide a type to  Array#newInstance.  Finally, the result from Array#newInstance is cast to T[] to create a generic array.

6. Creating Arrays From Streams

The Java Streams API allows us to create arrays from the items in the stream. There are a couple of pitfalls to watch out for to ensure we produce an array of the correct type.

6.1. Using  toArray

We can easily convert the items from a Java 8 Stream into an array:

We should note, however, that the basic toArray function provides us with an array of  Object , rather than an array of  String :

As we saw earlier, the precise type of each array is different. As the type in a  Stream is generics, there’s no way for the library to infer the type at runtime .

6.2. Using the toArray Overload to Get a Typed Array

Where the common collection class methods use reflection to construct an array of a specific type, the Java Streams library uses a functional approach. We can pass in a lambda, or method reference, which creates an array of the correct size and type when the Stream is ready to populate it:

The method we pass is an IntFunction, which takes an integer as input and returns a new array of that size. This is exactly what the constructor of String[] does, so we can use the method reference String[]::new .

6.3. Generics With Their Own Type Parameter

Now let’s imagine we want to convert the values in our stream into an object which itself has a type parameter, say  List or  Optional . Perhaps we have an API we want to call that takes  Optional<String>[] as its input.

It’s valid to declare this sort of array:

We can also easily take our  Stream<String> and convert it to  Stream<Optional<String>> by using the  map method:

However, we’d again get a compiler error if we tried to construct our array:

Luckily, there’s a difference between this example and our previous examples. Where String[] isn’t a subclass of Object[] ,  Optional[] is actually an identical runtime type to  Optional<String>[] . In other words, this is a problem we can solve by type casting:

This code compiles and works, but gives us an unchecked assignment warning. We need to add a SuppressWarnings to our method to fix this:

6.4. Using a Helper Function

If we want to avoid adding the  SuppressWarnings to multiple places in our code, and wish to document the way our generic array is created from the raw type, we can write a helper function:

This function converts the function to make an array of the raw type into a function that promises to make an array of the specific type we need:

The unchecked assignment warning doesn’t need to be suppressed here.

We should note, however, that this function can be called to perform type casts to higher types. For example, if our stream contained objects of type List<String> , we might incorrectly call  genericArray to produce an array of  ArrayList<String> :

This would compile, but would throw a ClassCastException, as ArrayList[] isn’t a subclass of List[]. The compiler produces an unchecked assignment warning for this though, so it’s easy to spot.

7. Conclusion

In this article, we examined the differences between arrays and generics. Then we looked at an example of creating a generic array, demonstrating how using an ArrayList may be easier than using a generic array. We also discussed the use of a generic array in the Collections API.

Finally, we learned how to produce arrays from the Streams API, and how to handle creating arrays of types that use a type parameter.

As always, the example code is available over on GitHub.

Just published a new writeup on how to run a standard Java/Boot application as a Docker container, using the Liberica JDK on top of Alpaquita Linux:

>> Spring Boot Application on Liberica Runtime Container.

Slow MySQL query performance is all too common. Of course it is.

The Jet Profiler was built entirely for MySQL , so it's fine-tuned for it and does advanced everything with relaly minimal impact and no server changes.

Explore the secure, reliable, and high-performance Test Execution Cloud built for scale. Right in your IDE:

Basically, write code that works the way you meant it to.

Build your API with SPRING - book cover

The Java Tutorials have been written for JDK 8. Examples and practices described in this page don't take advantage of improvements introduced in later releases and might use technology no longer available. See Java Language Changes for a summary of updated language features in Java SE 9 and subsequent releases. See JDK Release Notes for information about new features, enhancements, and removed or deprecated options for all JDK releases.

Lesson: Generics (Updated)

In any nontrivial software project, bugs are simply a fact of life. Careful planning, programming, and testing can help reduce their pervasiveness, but somehow, somewhere, they'll always find a way to creep into your code. This becomes especially apparent as new features are introduced and your code base grows in size and complexity.

Fortunately, some bugs are easier to detect than others. Compile-time bugs, for example, can be detected early on; you can use the compiler's error messages to figure out what the problem is and fix it, right then and there. Runtime bugs, however, can be much more problematic; they don't always surface immediately, and when they do, it may be at a point in the program that is far removed from the actual cause of the problem.

Generics add stability to your code by making more of your bugs detectable at compile time. After completing this lesson, you may want to follow up with the Generics tutorial by Gilad Bracha.

About Oracle | Contact Us | Legal Notices | Terms of Use | Your Privacy Rights

Copyright © 1995, 2022 Oracle and/or its affiliates. All rights reserved.

  • All Articles List
  • 13 May 2020

Using varargs when working with generics

By the way, do you remember what varargs is.

Java webinar

18 Java Collections and Generics Best Practices

1. Choosing the right collections

2. Always using interface type when declaring a collection

3. use generic type and diamond operator, 4. specify initial capacity of a collection if possible.

5. Prefer isEmpty() over size()

6. Do not return null in a method that returns a collection

7. do not use the classic for loop, 8. favor using foreach() with lambda expressions, 9. overriding equals() and hashcode() properly, 10. implementing the comparable interface properly, 11. using arrays and collections utility classes, 12. using the stream api on collections, 13. prefer concurrent collections over synchronized wrappers, 14. using third-party collections libraries, 15. eliminate unchecked warnings, 16. favor generic types, 17. favor generic methods, 18. using bounded wildcards to increase api flexibility, 1. choosing th e right colle ctions.

- Does it allow duplicate elements?

- Does it accept null?

- Does it allow accessing elements by index?

- Does it offer fast adding and fast removing elements?

- Does it support concurrency?

  • Java List Tutorial
  • Java Map Tutorial
  • Java Queue Tutorial
  • Java Set Tutorial

5 . Prefer isEmpty() over size()

- HashMap -> ConcurrentHashMap

- ArrayList -> CopyOnWriteArrayList

- TreeMap -> ConcurrentSkipListMap

- PriorityQueue -> PriorityBlockingQueue

- Fastutil : This library is a great choice for collections of primitive types like int or long . It’s also able to handle big collections with more than 2.1 billion elements (2^31) very well.

- Guava : This is Google core libraries for Java 6+. It contains a magnitude of convenient methods for creating collections, like fluent builders, as well as advanced collection types like HashBiMap , ArrayListMultimap , etc.

- Eclipse Collections : this library includes almost any collection you might need: primitive type collections, multimaps, bidirectional maps and so on.

- JCTools : this library provides Java concurrency tools for the JVM. It offers some concurrent data structures currently missing from the JDK such as advanced concurrent queues.

Other Java Collections Tutorial:

  • Java Stream API Tutorial
  • Understand equals and hashCode in Java
  • Understand object ordering in Java
  • How to write generic classes and methods in Java

About the Author:

java generics unchecked assignment

Add comment

   

Notify me of follow-up comments

Comments  

Stack Exchange Network

Stack Exchange network consists of 183 Q&A communities including Stack Overflow , the largest, most trusted online community for developers to learn, share their knowledge, and build their careers.

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

How can I avoid unchecked cast warning in my generic recursive Iterator?

It's somewhat odd that Java's collection framework has no iterator for recursive data structures. Since I needed something like this, I wrote my own. First off, I need recursive elements:

And then an Iterator :

That code works very well, but I do get a warning from the compiler in the next() method in the line I marked. It is clear to me why this warning occurs, but I have not come up with any solution on how to solve the problem without this warning (save suppressing the warning). Any ideas?

Jamal's user avatar

  • \$\begingroup\$ I don't think you can. Java's generics doesn't allow compound types such as Iterator<T | RecursiveElement<T>> . \$\endgroup\$ –  David Harkness Commented Apr 16, 2014 at 17:39

2 Answers 2

I don't think you can do anything about this. You have to cast here, and in the process you lose all information about the type parameter: The compiler can't know that if you have a RecursiveElement , it's always a RecursiveElement<T> , and "thanks" to type erasure it can't check the runtime type.

Landei's user avatar

  • 1 \$\begingroup\$ As @JvR points out, the problem isn't type erasure but the fact that each collection may contain both items and other collections. This necessitates a cast from T to RecursiveElement<T> which the compiler does not like (rightly so). \$\endgroup\$ –  David Harkness Commented Apr 16, 2014 at 17:34

The type checker is marking a real issue here. To visualise this, replace your RecursiveElement<T> with a generic Iterable<T> , which provides identical type guarantees.

When different layers mix different types, RecursiveIterator unfortunately breaks down. Here is an example:

Your options are:

  • try to push the responsibility of recursing to your actual elements;
  • try some wizardry to accept a finite amount of recursion by adding type variables;
  • drop type safety and wrap in a filtering iterator.

JvR's user avatar

Your Answer

Sign up or log in, post as a guest.

Required, but never shown

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy .

Not the answer you're looking for? Browse other questions tagged java recursion casting iterator or ask your own question .

  • The Overflow Blog
  • Community Products Roadmap Update, July 2024
  • Featured on Meta
  • We spent a sprint addressing your requests — here’s how it went
  • Upcoming initiatives on Stack Overflow and across the Stack Exchange network...

Hot Network Questions

  • Why is there not a test for diagonalizability of a matrix
  • The object modified by relative clauses
  • How to photograph the lettering on a bronze plaque?
  • Are there alternative statistics to a p-value in NHST?
  • Is "necesse est tibi esse placidus" valid classical Latin?
  • Are there rules for gender of durations?
  • ForeignFunctionLoad / RawMemoryAllocate and c-struct that includes an array
  • Confusion on defining uniform distribution on hypersphere and its sampling problem
  • How much does a factory reset help in hiding a device's identification details?
  • Who is the distant man in the final frames?
  • Decorate equations with arrows using TikZ
  • I forgot to remove all authors' names from the appendix for a double-blind journal submission. What are the potential consequences?
  • firefox returns odd results for file:/// or file:///tmp
  • Can the differential be unitless while the variable have an unit in integration?
  • \AddToShipOutPicture on every second page
  • 2024 UK election: Which demographic factors explain the geography?
  • Visa requirements for British passport holders going to Ghana via Brussels
  • Can you be charged with breaking and entering if the door was open, and the owner of the property is deceased?
  • Everything has a tiny nuclear reactor in it. How much of a concern are illegal nuclear bombs?
  • How to optimize performance with DeleteDuplicates?
  • Was I wrongfully denied boarding for a flight where the airliner lands to a gate that doesn't directly connect to the international part the airport?
  • What spells can I cast while swallowed?
  • Do thermodynamic cycles occur only in human-made machines?
  • What is the correct translation of the ending of 2 Peter 3:17?

java generics unchecked assignment

Should `type(x)` perform type erasure for generics?

Consider the following:

Now mypy ( playground ), pyright ( here ) and pyre ( here ) show type[list[int]] as revealed type and reject the call. pytype (no playground available) also reveals Type[List[int]] , but accepts the following call. Seems like there’s some consensus regarding this, and only pytype doesn’t follow it - but was it a deliberate decision?

IMO last line should really mean “please build a list from string” rather than “please build a list[int] from string” - why is the generic type not erased there?

What am I missing? Looks like type(x) should be type-erased: it is indeed safe to construct instances parameterized by a different generic type, and all the necessary mechanics to fall back to the original constructor and check the call do already exist. I’d expect the type checker to accept such construct, because semantically type(x)(...) is “please treat this as a new constructor call for the type”. Since type(x) does not contain any additional type information at runtime, why should it be restricted to the same set of parameters? type(list[int]()) is still <class 'list'> , it doesn’t know anything about previous generics specified.

I’m raising this as a public question, because type(x)(...) is a pretty common idiom for “build another instance of same type”. Inspired by this StackOverflow question .

This problem is not addressed directly in the typing spec, and probably deserves some place there.

At runtime type(x) is just list , not list[int] , so I think that’s ideally what type checkers should infer too.

The type checkers you flag should therefore probably change their behavior.

For both mypy and pyright it is possible to construct an example where the type checker behaves incorrectly because of this behavior:

Oh wow, I agree that type(x) is Something[Parametrized] should be unconditionally a typecheck warning right away (like mypy’s comparison-overlap code) and Never in branch - I didn’t even consider such case. Thanks!

I think the current behavior of pyright, pyre, and mypy is arguably correct. Changing this behavior would likely create more problems than it solves.

There are many examples where the runtime erases types but a type checker does not, so I think it’s a weak argument that type checkers must match the runtime behavior in this case.

If we were to change the typing spec to indicate that type checkers must erase generic types for type(x) , the resulting type would presumably need to replace all of the type arguments with Any (and ... for ParamSpecs, *tuple[Any, ...] for TypeVarTuples). That’s probably not what most developers would expect, and it would mask type errors that are caught today. It also wouldn’t catch the error in Jelle’s example above .

Regarding the IntList example, the underlying problem there is perhaps the fact that __init__ is not checked for LSP violations, which makes any use of type(x)(...) arguably unsafe. It is also possible to come up with examples that are unsafe under the current behavior (e.g., if IntList.__init__ does not accept an iterable).

I think in my example, the mistake type checkers are making is that they accept a parameterized generic on the right-hand side of a type(...) is ... comparison, which is incorrect since type() never returns a parameterized generic. That’s perhaps a separate issue from the problem of what type() itself returns.

Yeah, thank you - that answers my question fully. I didn’t consider specialization upcasting: indeed, we can’t be sure that something typed as list[int] can be parameterized by any other type. Your IntList is the reason why type erasure is not allowed here.

Related Topics

Topic Replies Views Activity
Typing 11 1954 November 26, 2023
Typing 21 383 June 28, 2024
Typing 29 789 March 8, 2024
Typing 7 588 January 31, 2024
Python Help 1 4806 July 24, 2022
  • Stack Overflow for Teams Where developers & technologists share private knowledge with coworkers
  • Advertising & Talent Reach devs & technologists worldwide about your product, service or employer brand
  • OverflowAI GenAI features for Teams
  • OverflowAPI Train & fine-tune LLMs
  • Labs The future of collective knowledge sharing
  • About the company Visit the blog

Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Get early access and see previews of new features.

Using generics to create a node traversal class?

Does anyone know the best way to approach this problem?

I'm getting the following error, which I assume means I need a different approach to compare the data element of the node.

dani-vta's user avatar

  • 4 You should look into implementing Comparable for your Node / V classes. –  Dan W Commented Jul 1 at 19:16
  • 1 < in Java is only valid for numbers (byte, char, short, int, long). V is not a number, so you cannot use < with it. But you can provide a custom Comparator to compare your values. In any case, you must define what it means for one V to be smaller than another V. –  knittl Commented Jul 1 at 19:20

2 Answers 2

As already suggested in the comments by @Dan W, the generic type V in the Node class should define an upper bound to Comparable in order to restrict the possible types in place of V to only the ones that can be compared (ordered).

In Java, the operators < , > , <= , >= can be used only for numeric primitive types, such as int , float , double , and so on. Instead, to compare reference types, their class needs to implement the Comparable interface to define a natural ordering among their elements.

This interface imposes a total ordering on the objects of each class that implements it. This ordering is referred to as the class's natural ordering, and the class's compareTo method is referred to as its natural comparison method.

Most Java classes like Integer , Float , Double and many others already implement the Comparable interface, while for your own classes you need to provide the comparison logic within the compareTo method. Here is also a great article from Bealdung with a guide on how to implement the Comparable interface.

In your case, a generic version of your class Node can be re-written in the following way:

In the previous snippet, the type parameter for Comparable is written with a lower bounded wildcard ( Comparable<? super V> ) instead of just the generic parameter V ( Comparable<V> ), so that classes that do not implement directly the Comparable interface can be accepted as well when their supertypes actually do. This is the case, for example, for the LocalDate class, which does not implement Comparable directly, but its supertype ChronoLocalDate actually does. Like so, also LocalDate instances can be accepted and confronted.

A particular thank you to @Holger for pointing this out in the comments.

  • 1 The declaration should be class Node<V extends Comparable<? super V>> . It makes a difference when the application wants to use it like Node<LocalDate> , for example. And, as a side note to the OP, don’t forget to add the else part inserting into the right branch… –  Holger Commented Jul 2 at 10:05
  • Hi @Holger, thanks a lot for your comment! I've just updated my answer. –  dani-vta Commented 2 days ago

You're getting this error because compiler does not know if V is a type that supports comparison with < . You can use compareTo() method to compare generic type elements. Check this for more info .

Batman's user avatar

  • 1 Note that compareTo() is only available if the types are required to implement Comparable: class Node<V extends Comparable> –  ipodtouch0218 Commented Jul 1 at 19:40

Your Answer

Reminder: Answers generated by artificial intelligence tools are not allowed on Stack Overflow. Learn more

Sign up or log in

Post as a guest.

Required, but never shown

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy .

Not the answer you're looking for? Browse other questions tagged java generics or ask your own question .

  • The Overflow Blog
  • Community Products Roadmap Update, July 2024
  • Featured on Meta
  • We spent a sprint addressing your requests — here’s how it went
  • Upcoming initiatives on Stack Overflow and across the Stack Exchange network...
  • The [lib] tag is being burninated
  • What makes a homepage useful for logged-in users

Hot Network Questions

  • pdfgrep How to locate the pages that contain multiple strings and print the page numbers?
  • When can まで mean "only"?
  • Reversing vowels in a string
  • Simulate slow disks in KVM to see effect of LVM cache in test setup
  • Any alternative to lockdown browser?
  • A check given by castling: is it a discovered check or a special case?
  • When selling a machine with proprietary software that links against an LGPLv3 library, do I need to give the customer root access?
  • How close would a quasar have to be to be seen with the naked eye?
  • How much does a factory reset help in hiding a device's identification details?
  • Is there any evidence of reasoning or argument in ancient texts outside Ancient Greece?
  • What is the reason for using decibels to measure sound?
  • ForeignFunctionLoad / RawMemoryAllocate and c-struct that includes an array
  • Challenge the appointment of the prime minister
  • Capture multiple errors before raising an exception
  • Selecting random effects in a linear mixed model when all participants complete all repeated measures?
  • Why does the length of an antenna matter when electromagnetic waves propagate perpendicular to the antenna?
  • Do thermodynamic cycles occur only in human-made machines?
  • When do people say "Toiletten" in the plural?
  • Why did Nigel Farage choose Clacton as the constituency to campaign in?
  • Plastic plugs used to fasten cover over radiator
  • Are US enlisted personnel (as opposed to officers) required, or allowed, to disobey unlawful orders?
  • Is the FRW metric, based on spatial homogeneity and isotropy, rotationally and translationally invariant? If so, how?
  • Why do Electric Aircraft Seem to Eschew Photovoltaics?
  • Is there a way to change a cantrip spell type to Necromancy in order to fulfil the requirement of the Death Domain Reaper ability for Clerics?

java generics unchecked assignment

IMAGES

  1. Checked and Unchecked Exceptions in Java

    java generics unchecked assignment

  2. What Is Generics In Java With Example ?

    java generics unchecked assignment

  3. Checked and Unchecked Exceptions in Java With Examples

    java generics unchecked assignment

  4. Checked and Unchecked Exceptions in Java

    java generics unchecked assignment

  5. Java Generics Made Easy: An Introduction for Beginners

    java generics unchecked assignment

  6. Checked and Unchecked Exceptions in Java

    java generics unchecked assignment

VIDEO

  1. How to handle Checked vs Unchecked Exceptions in Java #java #javaprogramming

  2. Additional.Generics.feb2013 (часть3)

  3. Java for Testers

  4. Mastering Java Fundamentals with These Fun Riddles!Part 1

  5. Java

  6. What are unchecked exceptions in java?

COMMENTS

  1. java

    Map<Integer, String> map = a.getMap(); gets you a warning now: "Unchecked assignment: 'java.util.Map to java.util.Map<java.lang.Integer, java.lang.String>'. Even though the signature of getMap is totally independent of T, and the code is unambiguous regarding the types the Map contains. I know that I can get rid of the warning by reimplementing ...

  2. generics

    I'm using the following code to find a one-dimensional list of unique objects in an n-dimensional list (credits to someone on StackOverflow a while ago for the approach): public static <T> List<T> getUniqueObjectsInArray(List<T> array) {. Integer dimension = getDimensions(array); return getUniqueObjectsInArray(array, dimension);

  3. Java Warning "Unchecked Cast"

    The "unchecked cast" is a compile-time warning . Simply put, we'll see this warning when casting a raw type to a parameterized type without type checking. An example can explain it straightforwardly. Let's say we have a simple method to return a raw type Map: public class UncheckedCast {. public static Map getRawMap() {.

  4. Introducing Generics

    Generics enable types (classes and interfaces) to be parameters when defining classes, interfaces and methods. ... Example.java uses unchecked or unsafe operations. Note: Recompile with -Xlint:unchecked for details. ... this is called an "is a" relationship. Since an Integer is a kind of Object, the assignment is allowed. But Integer is also a ...

  5. How to Avoid Unchecked Casts in Java Programs

    Using Generics to Avoid Unchecked Casts in Java In Java, Generics is a powerful feature that allows you to write classes and methods that are parameterized by one or more types. Generics are a way of making your code more type-safe and reusable. With generics, you can define classes and methods that work on a variety of types, without having to ...

  6. Guide to Understanding Generics in Java

    Introduction. Java is a type-safe programming language. Type safety ensures a layer of validity and robustness in a programming language. It is a key part of Java's security to ensure that operations done on an object are only performed if the type of the object supports it.. Type safety dramatically reduces the number of programming errors that might occur during runtime, involving all kinds ...

  7. Java Warning "unchecked conversion"

    This assignment is allowed by the compiler because the compiler has to allow this assignment to preserve backward compatibility with older Java versions that do not support generics.. An example will explain it quickly. Let's say we have a simple method to return a raw type List:. public class UncheckedConversion { public static List getRawList() { List result = new ArrayList(); result.add ...

  8. Generics

    Generics. When you take an element out of a Collection, you must cast it to the type of element that is stored in the collection. Besides being inconvenient, this is unsafe. The compiler does not check that your cast is the same as the collection's type, so the cast can fail at run time. Generics provides a way for you to communicate the type ...

  9. Generics in Java

    Generics means parameterized types. The idea is to allow type (Integer, String, … etc., and user-defined types) to be a parameter to methods, classes, and interfaces. Using Generics, it is possible to create classes that work with different data types. An entity such as class, interface, or method that operates on a parameterized type is a ...

  10. Generics unchecked assignment (Java in General forum at Coderanch)

    The most generic way of using generics is. This causes "Unchecked assignment: 'java.util.Set' to 'java.util.Collection <?

  11. Creating a Generic Array in Java

    The loose types of Java generics are hard to coerce into the strong types of Java arrays. We explore the problem and some common solutions. ... The compiler produces an unchecked assignment warning for this though, so it's easy to spot. 7. Conclusion. In this article, we examined the differences between arrays and generics.

  12. Lesson: Generics (Updated) (The Java™ Tutorials

    Lesson: Generics (Updated) In any nontrivial software project, bugs are simply a fact of life. Careful planning, programming, and testing can help reduce their pervasiveness, but somehow, somewhere, they'll always find a way to creep into your code. This becomes especially apparent as new features are introduced and your code base grows in size ...

  13. Taming a Silly Generic Warning

    Unchecked assignment: java.util.List to java.util.List<String> ... Now it all works, and I don't have to fight those generic types when using the mock method (or, for that matter, ...

  14. Java Varargs with examples

    A reifiable type is a type for which information is fully available at runtime. In Java, such types include primitives, raw types, and non-generic types. In contrast, non-reifiable types are types whose information is erased and becomes inaccessible at runtime. As it happens, these are generics — List<String>, List<Integer>, etc.

  15. Item 27: Eliminate unchecked warnings

    The more experience you acquire with generics, the fewer warnings you'll get, but don't expect newly written code to compile cleanly. Many unchecked warnings are easy to eliminate. For example, suppose you accidentally write this declaration: Set<Lark> exaltation = new HashSet(); The compiler will gently remind you what you did wrong:

  16. How to Avoid Unchecked Casts in Java Programs

    Unchecked casts are a common source of Java program errors. Here are some examples of unchecked casts: List names = (List) obj; // cast Object to List. This cast statement above can result in a ...

  17. generics

    Sadly, you can't add generics to enum s (it's on a future Java feature list), so you won't be able to safely do that. The only way to get rid of the warning is to suppress it. As a side note, you could just use a java.util.Function<T, R> rather than defining your own functional interface. answered Dec 5, 2019 at 13:25.

  18. 18 Java Collections and Generics Best Practices

    Perhaps you will see some practices are new, some you already knew but the key point is that, you should consider these useful practices and apply them quickly into your daily coding. Here's the list: 1. Choosing the right collections. 2. Always using interface type when declaring a collection. 3.

  19. java

    The type checker is marking a real issue here. To visualise this, replace your RecursiveElement<T> with a generic Iterable<T>, which provides identical type guarantees.. When different layers mix different types, RecursiveIterator unfortunately breaks down. Here is an example:

  20. Java Generics, how to avoid unchecked assignment warning when using

    I want to use a method using generic parameters and returning generic result on a class hierarchy. edit: no SupressWarnings("unchecked") answer allowed :-) Here is a sample code illustrating my problem:

  21. Federal Circuit Clarifies Rules for Skinny Labeling for Generics and

    Last week, the Federal Circuit decided Amarin Pharma, Inc. v. Hikma Pharmaceuticals USA Inc., 23-1169 (Fed. Cir. June 25, 2024), a case that spotlighted the issues of skinny labeling and induced infringement for generic pharmaceuticals and provided lessons for both innovator and generic companies.The core lesson is that generics and biosimilar companies must be extremely cautious in making ...

  22. Should `type(x)` perform type erasure for generics?

    Consider the following: x: list[int] = [1] reveal_type(type(x)) type(x)('abc') Now mypy (playground), pyright (here) and pyre (here) show type[list[int]] as revealed type and reject the call. pytype (no playground available) also reveals Type[List[int]], but accepts the following call. Seems like there's some consensus regarding this, and only pytype doesn't follow it - but was it a ...

  23. java

    I get "Unchecked assignment: java.util.List to java.util.List<java.lang.Integer>" at the line with the comment.The warning is cleared when the GetList parameter is changed to GetList<?>.. I don't understand why the GetList generic type would influence the outcome of getIntegerList().Tried in both Intellij Idea and Eclipse. Is it normal or is the warning message wrong?

  24. java

    As already suggested in the comments by @Dan W, the generic type V in the Node class should define an upper bound to Comparable in order to restrict the possible types in place of V to only the ones that can be compared (ordered).. In Java, the operators <, >, <=, >= can be used only for numeric primitive types, such as int, float, double, and so on.. Instead, to compare reference types, their ...