Pablo
Pablo

Reputation: 3467

Null pointer exception when working with generics in java

since I have not been using generics for some time, I'm quite confused at this example.

I have the following base abstract class:

public abstract class ExcelReader<T>{
     protected T type;
     protected GenericResolver resolver;

     public ExcelReader(){
        super();
        resolver=ResolverFactory.createResolver(type.getClass()); 
     }
}

now my subclass is the following:

public class POIReader<T> extends ExcelReader<T>{

}
//...Implementation of methods ommited for brevity

Now in my service I'm creating a new object in the following way:

ExcelReader<MessageDTO> reader=new POIReader<MessageDTO>();

However, when the ExcelReader constructor is called the type attribute has null, and in consecuence throwing a NullPointer exception when creating the resolver.

I think you can get the idea of what I'm trying to do with the code fragments above, and I have seen examples using an attribute field to save the Parametized Class type.

However I'm quite confused in why I'm getting null in the type attribute, and how could I avoid it. Thanks a lot.

Upvotes: 4

Views: 1781

Answers (3)

Seramme
Seramme

Reputation: 1350

I don't think you are trying to use the generics for the thing they were intended to use. Generics are a kind of "syntactic sugar" usable in compile-time only as an additional level of code validation. What you seem to want to achieve - correct me if I am wrong - is to provide the generic type to your POIReader class and then be able (in runtime) to access this type's class object. Is this correct?

The way you could use the generics in your example - but I am not sure this will be what you want to achieve - is for something like this:

public abstract class ExcelReader<T>{
     protected T value;
     protected GenericResolver resolver;

     public ExcelReader(T value) {
        super();
        resolver=ResolverFactory.createResolver(type.getClass()); 
     } 
}

public class POIReader<T> extends ExcelReader<T>{
    public POIReader(T value) {
        super(value);
    }
}

and then:

MessageDTO yourObject = ...;
ExcelReader<MessageDTO> reader=new POIReader<MessageDTO>(yourObject);

This way, thanks to using generics the compiler will not allow you to pass anything that is not assignable to a MessageDTO class as the argument to POIReader's constructor - but you still must assign something to that value field in order to be able to call the getClass() method. This is because, due to type erasure of generics (an unfortunate backwards-compatibility thing), generics you provide are not available in runtime, only in compile-time.

Upvotes: 0

AlexR
AlexR

Reputation: 115378

You exactly explained the problem. The type is null. So, what do you have to do? Make it not null. Modify constructor as folloiwing:

 protected ExcelReader(T type){
    super();
    this.type = type;
    resolver=ResolverFactory.createResolver(type.getClass()); 
 }

Now your subclass must send this parameter, e.g.

public class POIReader extends ExcelReader<MessageDTO>{
    public POIReader() {
        super(MessageDTO.class);
    }
}

Alternatively you can make your subclass generic too, so the responsibility on sending the type is moved to client:

public class POIReader<T> extends ExcelReader<T>{
    public POIReader(Class<T> type) {
        super(type);
    }
}

// and call it:
new POIReader(MessageDTO.class);

Upvotes: 0

Jon Skeet
Jon Skeet

Reputation: 1502116

You're calling type.getClass() but at that point type is guaranteed to be null. No other code will have had a chance to set it yet, so how did you expect it to work? You say you're confused about why it's null - but you haven't shown anything which would make it non-null.

I suspect you want something like:

public abstract class ExcelReader<T>{
     protected final Class<T> type;
     protected GenericResolver resolver;

     public ExcelReader(Class<T> type){
        this.type = type;
        resolver = ResolverFactory.createResolver(type); 
     }
}

You'd want to introduce the same sort of parameter on the subclasses too.

Upvotes: 13

Related Questions