3

In my code, when I try to deserialize the HashSet object it gives me this warnings :

Unchecked assignment:'java.util.HashSet' to'java.util.HashSet<java.lang.Integer>
Inspection info: Signals places where an unchecked warning is issued
by the compiler, for example:
 void f(HashMap map) {  map.put("key", "value"); }
Hint: Pass -Xlint:unchecked to javac to get more details.

Is this a critical warning ? or should I use @SuppressWarnig ?

How can I eliminate this warning ? please help me guys I'm new in Java

My Code is :

public class Main{
    public static void main(String[] args){
    HashSet<Integer> number=new HashSet<>();
    Scanner input=new Scanner(System.in);
    int option;
    while(true){
        System.out.println("1. add 2. display 3. save 4. load 5. exit");
        option=input.nextInt();
        if(option==1){
            System.out.println("Adding : "+ number.add(1));
            System.out.println("Adding : " + number.add(2));
        }else if(option==2){
            System.out.println("Set is : "+ number);
        }else if(option==3){
            try{
                FileOutputStream fos=new FileOutputStream("data.bin");
                ObjectOutputStream oos=new ObjectOutputStream(fos);
                oos.writeObject(number);
                oos.close();
                fos.close();
            }catch(IOException e){
                e.getMessage();
            }
        }else if(option==4){
            try{
                FileInputStream fis=new FileInputStream("data.bin");
                ObjectInputStream ois=new ObjectInputStream(fis);
                number=(HashSet)ois.readObject(); // this line give me warning
            }catch(IOException | ClassNotFoundException e){
                e.getMessage();
            }
        }else if(option==5){
            break;
        }
    }
}
}
Naman
  • 27,789
  • 26
  • 218
  • 353
H.Das
  • 225
  • 2
  • 9

1 Answers1

3

There is no (easy) way to write the code such that you won't get this warning. It is non-critical, you can probably ignore it.

Why is it happening?

Generics are a figment of the compiler's imagination. your serialized stream of bytes only stores that you've saved a HashSet object, it does not store the <Integer> part, nor can it, because that information is no longer present at runtime.

When you store the object you load back from your serialized stream into the number variable, java has no idea if the hashset in fact contains only Integer instances, and at runtime this isn't checked. If it contains strings for example, so be it, and later you'll get a ClassCastException if that is the case.

The warning specifically means: "Okay, you are asserting that this HashSet you just got from the serialization system contains only integers. There is no compile-time way for javac to verify this, and this cast will not generate runtime code to do it either. Therefore, we're just going by your say so, so let's hope that you're right! If not, ClassCastExceptions will occur later in weird places."

How can I avoid it?

One way is to assign first to a variable of type HashSet<?>, then loop through it, check for each value if it is an integer, if yes put it in number, if no exit the method with a proper error message. Casting individual members of the set IS possible and does not get the warning.. but now you are spending an extra loop.

An even better solution is to not use java's built in serialization mechanism in the first place. It is complicated, tends to lend itself to security issues, it's hard to deal with expanding needs (it's hard to change versions or load/write it from other languages), it is not human readable, and it is not space efficient.

Try for example Jackson to serialize your objects.

rzwitserloot
  • 85,357
  • 5
  • 51
  • 72
  • Another viewpoint on why you shouldn't use java serialization: https://www.infoworld.com/article/3275924/java/oracle-plans-to-dump-risky-java-serialization.html – nareddyt Feb 09 '19 at 15:45
  • Jackson doesn't actually solve the problem. It's just that the stored data does not even contain the information that it previously was a `HashSet`. So you are requesting a `HashSet` when restoring and the data will get converted to it similar to the way you've described. Of course, you could do the same with Serialization, e.g. copy all values into an integer array, serialize it and when deserializing, copy the array to a new `HashSet`. – Holger Feb 09 '19 at 18:06