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

gleidsonleite profile image

Exploring Microfrontends with Vite and React: A Step-by-Step Guide

Gleidson Leite da Silva - Aug 24

hardikidea profile image

Immer : Clear understanding of how to handle nested state objects with Immer in React and TypeScript

Er Hardik Chauhan - Aug 24

pelikhan profile image

Keeping the Your README Fresh and Engaging using AI

Peli de Halleux - Aug 24

dera2024 profile image

Deploying a Web App with ARM Templates and Azure CLI

Chidera Enyelu - Aug 24

DEV Community

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

  • 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

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 Course
  • 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
  • How to Get a Free SSL Certificate
  • Best SSL Certificates Provider in India
  • Elon Musk's xAI releases Grok-2 AI assistant
  • What is OpenAI SearchGPT? How it works and How to Get it?
  • Content Improvement League 2024: From Good To A Great Article

Improve your Coding Skills with Practice

 alt=

What kind of Experience do you want to share?

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.

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.

Workaround for unchecked cast of a deserialized Object to ArrayList<Vehicle>

For a class I was assigned to write code to read objects of the class Vehicle using ObjectInputStream ( in ). The objects are stored in an ArrayList called orders .

However, the compiler complains:

I always try to improve my code instead of ignoring or suppressing warnings. In this case, I have come up with a solution, but I'm trying to understand why it works, and if there is a better solution.

This update stops the warning:

Based on what I understand from what I've been reading, it works because (ArrayList<Vehicle>) obj may throw an exception if not all the elements are Vehicle . I am confused -- non-Vehicle objects can be added to the ArrayList even if its type parameter has been specified as Vehicle ? Also, is there a better solution, e.g. using instanceof ?

  • serialization

200_success's user avatar

  • 2 \$\begingroup\$ You cannot casts a Collection with generics parameter since the at runtime the generics information is not available (due to generics erasure ) and therefore the JVM cannot check that all elements in that Collection to be of that generics type. \$\endgroup\$ –  Timothy Truckle Commented Dec 30, 2017 at 11:56

In general, the Java compiler knows the type of each variable, at every point during the execution. And when you operate on incompatible types, the program won't compile.

When you cast an object to ArrayList<Vehicle> , the Java runtime environment can only ensure that the cast to ArrayList<something> succeeds, but due to backwards compatibility (Java 1.4 from 2002), the cast will succeed, no matter if the arraylist contains Integer or String or Vehicle objects. Therefore, in this situation, the compiler warning tells you: Hey, you are doing something that cannot be checked, make sure you know what you are doing.

Your code that first deserializes the list as a raw type ( ArrayList instead of ArrayList<Vehicle> ) doesn't produce the compiler warning since the raw ArrayList is equivalent to ArrayList<Object> , and you won't get a surprising ClassCastException when working with this list.

If you are sure that the serialized list will only ever contain objects of type Vehicle , you can safely ignore that warning. In my code, I have written a utility function like this:

Another way is to not serialize the list, but to create a wrapper class:

When you serialize this class and deserialize it, you still have to cast the type using (SerializedData) in.readObject() , but the warning goes away.

This still doesn't guarantee that the vehicles list contains only vehicles after deserialization, but that is an entirely different problem.

Roland Illig'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 serialization casting or ask your own question .

  • The Overflow Blog
  • Ryan Dahl explains why Deno had to evolve with version 2.0
  • From PHP to JavaScript to Kubernetes: how one backend engineer evolved over time
  • Featured on Meta
  • We've made changes to our Terms of Service & Privacy Policy - July 2024
  • Bringing clarity to status tag usage on meta sites

Hot Network Questions

  • Calculate the sum of numbers in a rectangle
  • Are there any virtues in virtue ethics that cannot be plausibly grounded in more fundamental utilitarian principles?
  • Can pedestrians and cyclists board shuttle trains in the Channel Tunnel?
  • How can one says that a particle IS a representation of some group?
  • Sticker on caption phone says that using the captions can be illegal. Why?
  • Jacobi two square's theorem last step to conclusion
  • How to extract code into library allowing changes without workflow overhead
  • Has the government of Afghanistan clarified what they mean/intend by the ban on 'images of living beings'?
  • Can the speed of light inhibit the synchronisation of a power grid?
  • Name of engineering civil construction device for flattening tarmac
  • What (if any) pre-breathes were "attempted" on the ISS, and why?
  • Book about a colony ship making an unscheduled stop in a star system with no habitable planets
  • Are automorphisms of matrix algebras necessarily determinant preservers?
  • What's the Matter?
  • What does the Fizeau experiment now do?
  • Postdoc supervisor has stopped helping
  • Is my electrical rough-in code compliant?
  • grep command fails with out-of-memory error
  • Efficiently tagging first and last of each object matching condition
  • Implement service registry servers with load balancing strategies
  • Vector of integers such that almost all dot products are positive
  • Is there anything that stops the majority shareholder(s) from destroying company value?
  • How do I do calculations with a sliding window while being memory-efficient?
  • How does quantum field theory affect the ontological tenability of composite objects?

java generics unchecked assignment

Checked and Unchecked Exceptions in Java

Last updated: January 8, 2024

java generics unchecked assignment

It's finally here:

>> The Road to Membership and Baeldung Pro .

Going into ads, no-ads reading , and bit about how Baeldung works if you're curious :)

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, visit the documentation page .

You can also ask questions and leave feedback on the Azure Container Apps GitHub page .

Java applications have a notoriously slow startup and a long warmup time. The CRaC (Coordinated Restore at Checkpoint) project from OpenJDK can help improve these issues by creating a checkpoint with an application's peak performance and restoring an instance of the JVM to that point.

To take full advantage of this feature, BellSoft provides containers that are highly optimized for Java applications. These package Alpaquita Linux (a full-featured OS optimized for Java and cloud environment) and Liberica JDK (an open-source Java runtime based on OpenJDK).

These ready-to-use images allow us to easily integrate CRaC in a Spring Boot application:

Improve Java application performance with CRaC support

Modern software architecture is often broken. Slow delivery leads to missed opportunities, innovation is stalled due to architectural complexities, and engineering resources are exceedingly expensive.

Orkes is the leading workflow orchestration platform built to enable teams to transform the way they develop, connect, and deploy applications, microservices, AI agents, and more.

With Orkes Conductor managed through Orkes Cloud, developers can focus on building mission critical applications without worrying about infrastructure maintenance to meet goals and, simply put, taking new products live faster and reducing total cost of ownership.

Try a 14-Day Free Trial of Orkes Conductor today.

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 .

Whether you're just starting out or have years of experience, Spring Boot is obviously a great choice for building a web application.

Jmix builds on this highly powerful and mature Boot stack, allowing devs to build and deliver full-stack web applications without having to code the frontend. Quite flexibly as well, from simple web GUI CRUD applications to complex enterprise solutions.

Concretely, The Jmix Platform includes a framework built on top of Spring Boot, JPA, and Vaadin , and comes with Jmix Studio, an IntelliJ IDEA plugin equipped with a suite of developer productivity tools.

The platform comes with interconnected out-of-the-box add-ons for report generation, BPM, maps, instant web app generation from a DB, and quite a bit more:

>> Become an efficient full-stack developer with Jmix

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

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

The AI Assistant to boost Boost your productivity writing unit tests - Machinet AI .

AI is all the rage these days, but for very good reason. The highly practical coding companion, you'll get the power of AI-assisted coding and automated unit test generation . Machinet's Unit Test AI Agent utilizes your own project context to create meaningful unit tests that intelligently aligns with the behavior of the code. And, the AI Chat crafts code and fixes errors with ease, like a helpful sidekick.

Simplify Your Coding Journey with Machinet AI :

>> Install Machinet AI in your IntelliJ

Since its introduction in Java 8, the Stream API has become a staple of Java development. The basic operations like iterating, filtering, mapping sequences of elements are deceptively simple to use.

But these can also be overused and fall into some common pitfalls.

To get a better understanding on how Streams work and how to combine them with other language features, check out our guide to Java Streams:

Download the E-book

Do JSON right with Jackson

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?

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

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

>> The New “REST With Spring Boot”

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

>> LEARN SPRING

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

1. Overview

Java exceptions fall into two main categories: checked exceptions and unchecked exceptions.

In this tutorial, we’ll provide some code samples on how to use them.

2. Checked Exceptions

In general, checked exceptions represent errors outside the control of the program. For example, the constructor of FileInputStream  throws FileNotFoundException if the input file does not exist.

Java verifies checked exceptions at compile-time.

Therefore, we should use the throws keyword to declare a checked exception:

We can also use a try-catch block to handle a checked exception:

Some common checked exceptions in Java are IOException , SQLException  and ParseException .

The Exception class is the superclass of checked exceptions, so we can create a custom checked exception by extending Exception :

3. Unchecked Exceptions

If a program throws an unchecked exception, it reflects some error inside the program logic.

For example, if we divide a number by 0, Java will throw ArithmeticException :

Java does not verify unchecked exceptions at compile-time. Furthermore, we don’t have to declare unchecked exceptions in a method with the throws  keyword. And although the above code does not have any errors during compile-time, it will throw ArithmeticException at runtime.

Some common unchecked exceptions in Java are NullPointerException , ArrayIndexOutOfBoundsException  and IllegalArgumentException .

The RuntimeException class is the superclass of all unchecked exceptions, so we can create a custom unchecked exception by extending RuntimeException :

4. When to Use Checked Exceptions and Unchecked Exceptions

It’s a good practice to use exceptions in Java so that we can separate error-handling code from regular code. However, we need to decide which type of exception to throw. The Oracle Java Documentation provides guidance on when to use checked exceptions and unchecked exceptions:

“If a client can reasonably be expected to recover from an exception, make it a checked exception. If a client cannot do anything to recover from the exception, make it an unchecked exception.”

For example, before we open a file, we can first validate the input file name. If the user input file name is invalid, we can throw a custom checked exception:

In this way, we can recover the system by accepting another user input file name.

However, if the input file name is a null pointer or it is an empty string, it means that we have some errors in the code. In this case, we should throw an unchecked exception:

5. Conclusion

In this article, we discussed the difference between checked and unchecked exceptions. We also provided some code examples to show when to use checked or unchecked exceptions.

As always, all code in this article can be found over on GitHub .

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.

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.

AI is all the rage these days, but for very good reason. The highly practical coding companion, you'll get the power of AI-assisted coding and automated unit test generation . Machinet's Unit Test AI Agent utilizes your own project context to create meaningful unit tests that intelligently aligns with the behavior of the code.

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

Build your API with SPRING - book cover

Follow the Java Category

java generics unchecked assignment

java generics unchecked assignment

Unchecked Assignment in java

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):

It works but I am still getting an 'unchecked assignment' warning when casting listitem to List in the following line listitem 为 List 时,我仍然收到“未检查分配”警告-->

Now I know I could just add @SuppressWarnings("unchecked") and it would hide the warning. @SuppressWarnings("unchecked") 并且它会隐藏警告。--> But is there a fundamentally different approach to doing this without this warning? Does it even matter in the end at all if this warning is there? Can fundamentally good code still contain warnings?

solution1  1 ACCPTED  2018-03-04 11:34:56

I don't see a way to get rid of that warning, as you you have to be very careful to declare and use the correct generic array types. So maybe you decide to ignore the warning...

  • A 1-dimensional array with elements of type T are correctly described by your List<T> declaration. List<T> 声明正确描述了具有 T 类型元素的一维数组。-->
  • A 2-dimensional array is a list, containing lists of elements, so that should be List<List<T>> . List<List<T>> 。-->
  • A 3-dimensional array is a list, containing lists of lists elements, so that should be List<List<List<T>>> . List<List<List<T>>> 。-->

The very core of your search is the recursive getUniqueObjectsInArray(...) method. getUniqueObjectsInArray(...) 方法。--> To get rid of the warning, you'd have to make sure that a call with eg List<List<List<String>>> produces a recursive (inner) call with List<List<String>> , and a dimension one less than before, so a first attempt would be something like: List<List<List<String>>> 的调用会产生一个带有 List<List<String>> 的递归(内部)调用,并且维度减少一比以前,所以第一次尝试将是这样的:-->

That also won't work, as the compiler won't allow you to do the recursive call, as he can't make sure that the listItem is a List. Let's try to tell him that by:

Now he knows that it's a list, but now that isn't enough, as now you need a List<List<whatever>> for calling getUniqueObjectsInArray(...) . List<List<whatever>> 来调用 getUniqueObjectsInArray(...) 。-->

You see, the attempts to do the right generics declaration so that the compiler doesn't warn, become quite complex, if at all possible. Honestly, I don't see a way to avoid the warnings, so don't spend too much time, and add @SuppressWarnings("unchecked").

solution2  0  2018-03-04 11:03:04

Well, I do not see the way to get rid of this warning since you perform down casting Object to List . Object to List 。-->

In your case the item in the list either could be some object or list , and you don't have generics support or other language construct that could describe this fact. 可以是某个 object 或 list ,并且您没有泛型支持或可以描述此事实的其他语言构造。-->

So as I see it at some point you need to perform casting operation.

The difference though is that what you have now is not safe: how exactly are you ensuring that here

that listItem is a subtype of a List ? listItem 是 List 的子类型?-->

What you can do is to try to bound you generic type and/or perform instance of checks to ensure correctness of the casting. instance of 以确保转换的正确性。-->

solution3  0  2018-03-04 11:24:49

You're implicitly casting all of your items in your list.

This example will compile without a warning because I am not casting the objects in the list to anything beside Object. If I switch ? ? --> to Integer , then I get a warning. Integer ,然后我收到警告。-->

solution4  -1  2018-03-04 10:10:10

This is because you are casting the object "listItem" to "List" without generic type parameters.

To get rid of this, just add the generic type parameters into the cast and it should get rid of the warning

  • Related Question
  • Related Blog
  • Related Tutorials

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:[email protected].

  • intellij-idea
  • executorservice
  • type-erasure
  • uncaught-exception
  • multithreading
  • 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.

Avoid unchecked assignment in a map with multiple value types?

I'm having trouble with a warning in Java 7:

I'm getting it on the line Class<T> type = typeMap.get(key); in the get function below.

Basically what I'm trying to do here is I want to store a bunch of key/value pairs of unknown types (but all are descendants of Object with the exception of null), but not lose the type. So I created a class with the following content using generics. It has two maps (one to store the data and one to store the class type:

It runs just fine, but the warning is annoying me. Is there any way to get Java to do this cast without complaining (other than suppressing it)? Or is there a better way to accomplish what I'm trying to do? How about in Java 8 as I haven't really had a chance to dive into it yet?

Radiodef's user avatar

  • The cast will be unsafe. Suppressing the warning might make you feel better, but your code isn't actually safe. –  Louis Wasserman Commented Mar 17, 2014 at 23:45
  • Have you tried private Map<String, Class<T>> typeMap = new HashMap<>()? –  JamesB Commented Mar 17, 2014 at 23:46
  • Do you know the types that will be used within the map? or do you wish it to hold ANY types? –  Chrisji Commented Mar 17, 2014 at 23:46

2 Answers 2

The reason what you've shown is unsafe is that with this assignment:

T does not need to have anything to do with the Class retrieved from the map. T is always inferred from the surrounding context of the call to get . For example I can do this sequence of calls:

Inside the get method, String.class is correctly retrieved from the type map, but an unchecked conversion is made to Class<Integer> . The call to type.cast(...) doesn't throw, because the value retrieved from the data map is a String . An implicit checked cast then actually happens to the return value , casting it to Integer and a ClassCastException is thrown.

This strange interaction is due to type erasure .

So, when we are storing multiple types in a single data structure, there are a number of ways to approach it, depending on what our needs are.

1. We can forego compilation checks if there is no way to perform them.

Storing the Class is pointless for the most part here because, as I showed above, it doesn't perform a useful validation. So we could redesign the map along the following lines:

getExplicit and getImplicit do a similar thing but:

In both cases we're just relying on our own awareness as a programmer to not make mistakes.

Suppressing warnings isn't necessarily bad, it's just important to understand what they actually mean and what the implications are.

2. Pass a Class to get so the return value must be valid.

This is the way I've seen it done typically.

But, of course, it means we need to pass two parameters to get .

3. Parameterize the keys.

This is a novel but more advanced and it may or may not be more convenient.

This might make sense if the entries are known or predictable so we can have something like:

Then we don't have to construct a key object any time a retrieval is done. This works very well especially for adding some strong typing to stringly-typed scenarios.

4. Don't have a map any kind of object can be put in, use polymorphism of some kind.

When possible and not too cumbersome, it's a good option. If there is a common behavior that the different types are used for, make it an interface or superclass so we don't have to use casting.

A simple example might be like this:

And we could instead substitute something like this:

You are attempting to assign an element of type Class to a variable of type Class<T> . Of course that's an unchecked assignment. You seem to be implementing a heterogeneous map. Java (and any other strongly-typed language) has no way to express the value type of your map in a statically-type-safe way.

That is because the element types are only known at runtime. Expecting the compiler to statically type-check things that are not yet known is asking too much of it. The compiler can't even do reasonable static type inference, so expecting it to predict the future for dynamic type inference is really a stretch.

Judge Mental's user avatar

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 casting or ask your own question .

  • The Overflow Blog
  • Ryan Dahl explains why Deno had to evolve with version 2.0
  • From PHP to JavaScript to Kubernetes: how one backend engineer evolved over time
  • Featured on Meta
  • We've made changes to our Terms of Service & Privacy Policy - July 2024
  • Bringing clarity to status tag usage on meta sites
  • Feedback requested: How do you use tag hover descriptions for curating and do...
  • What does a new user need in a homepage experience on Stack Overflow?

Hot Network Questions

  • Postdoc supervisor has stopped helping
  • Capitalization and Proper Nouns
  • How should I respond to a former student from my old institution asking for a reference?
  • One IO to control two LEDs. When one is lit, the other is not
  • 1970s? Novel, a man is stuck/trapped? in a city where the other people are fooled/conned into believing things are better than they are
  • If you get pulled for secondary inspection at immigration, missing flight, will the airline rebook you?
  • Does gluing two points prevent simple connectedness?
  • Meaning of capacitor "× 2" symbol on data sheet schematic
  • Can you successfully substitute pickled onions for baby onions in Coq Au Vin?
  • Why if gravity were higher, designing a fully reusable rocket would be impossible?
  • Idiomatic alternative to “going to Canossa”
  • what's the purpose of dependent claims?
  • Are there any virtues in virtue ethics that cannot be plausibly grounded in more fundamental utilitarian principles?
  • Why did Jesus choose to pray after they tried making him king?
  • Are chord inversions determined solely by the lowest note, even in a broken chord?
  • Which translation of Psalm 113:9 is closest to the original?
  • Thai word not breaking properly between lines, in LuaLaTeX
  • What is the difference between an `.iso` OS for a network and an `.iso` OS for CD?
  • What sort of impact did the discovery that water could be broken down (via electrolysis) into gas have?
  • What is the lesson of the Book of Iyov for the "average" person
  • Is the Shroud of Turin about 2000 years old?
  • Op Amp Feedback Resistors
  • Visualizing histogram of data on unit circle?
  • Why do combinatorists care about Kazhdan–Lusztig polynomials?

java generics unchecked assignment

IMAGES

  1. [Solved] Creating generic array in Java via unchecked

    java generics unchecked assignment

  2. Java Generics Example Tutorial

    java generics unchecked assignment

  3. Types of exceptions in Java: checked, unchecked, and custom

    java generics unchecked assignment

  4. Checked and Unchecked Exceptions in Java

    java generics unchecked assignment

  5. Checked and Unchecked Exceptions in Java

    java generics unchecked assignment

  6. List Of Checked And Unchecked Exceptions In Java

    java generics unchecked assignment

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 static Map getRawMap() {.

  4. 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 ...

  5. 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 ...

  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. 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 ...

  8. 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, ...

  9. 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 ...

  10. Creating a Generic Array in Java

    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: elements = (E[]) Array.newInstance(clazz, capacity); Notice how we use java.lang.reflect.Array#newInstance to initialize our generic array, which requires two parameters.

  11. How to Avoid Unchecked Casts in Java Programs

    Jun 1, 2023. 2. 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 ...

  12. 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:

  13. Java Warning "unchecked conversion"

    5.2. Checking Type Conversion Before Using the Raw Type Collection. The warning message " unchecked conversion " implies that we should check the conversion before the assignment. To check the type conversion, we can go through the raw type collection and cast every element to our parameterized type.

  14. java

    MacBook:Homework Brienna$ javac Orders.java -Xlint:unchecked Orders.java:152: warning: [unchecked] unchecked cast orders = (ArrayList<Vehicle>) in.readObject(); ^ required: ArrayList<Vehicle> found: Object 1 warning ... (due to generics erasure) and therefore the JVM cannot check that all elements in that Collection to be of that generics type ...

  15. 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.

  16. java

    Unchecked assignment: 'java.util.List[]' to 'java.util.List<java.lang.String>[]' java; Share. Follow edited Nov 12, 2020 at 15:46. ... krrbrr krrbrr. 3 5 5 bronze badges. 5. 1. Read about Generics in Java. Your list is of a raw type because it is missing type information preventing your compiler from checking them. - Smutje. Commented Nov 12 ...

  17. Generic programming

    Generic programming is a style of computer programming in which algorithms are written in terms of data types to-be-specified-later that are then instantiated when needed for specific types provided as parameters.This approach, pioneered by the ML programming language in 1973, [1] [2] permits writing common functions or types that differ only in the set of types on which they operate when used ...

  18. Checked and Unchecked Exceptions in Java

    Some common checked exceptions in Java are IOException, SQLException and ParseException. The Exception class is the superclass of checked exceptions, so we can create a custom checked exception by extending Exception: public IncorrectFileNameException(String errorMessage) {. super (errorMessage); 3.

  19. java

    solution4. -1 2018-03-04 10:10:10. This is because you are casting the object "listItem" to "List" without generic type parameters. To get rid of this, just add the generic type parameters into the cast and it should get rid of the warning. (List<T>) listItem. 提示: 若本文未解决您的问题,可以免费向大模型提问: 向AI ...

  20. Avoid unchecked assignment in a map with multiple value types?

    Of course that's an unchecked assignment. You seem to be implementing a heterogeneous map. Java (and any other strongly-typed language) has no way to express the value type of your map in a statically-type-safe way. That is because the element types are only known at runtime.