0

Im coming to Java from other languages, so please forgive me if this is obvious, but I've encountered a very strange behavior.

I'm writing a simple Pig UDF. I'm returning a Tuple object, which I create using a TupleFactory singleton. In the following two code examples, the first example works, while the second throws a NullPointerException when creating the newTuple;

public class MyUDF {

    public Tuple func(Tuple input) {
        return TupleFactory.getInstance().newTuple(Arrays.asList(o1, o2, o3));
    }
}

public class MyUDF {
    ...
    TupleFactory _factory;

    public Tuple func(Tuple input) {
        _factory.getInstance();
        return _factory.newTuple(Arrays.asList(o1, o2, o3));
    }
}
clo_jur
  • 1,359
  • 1
  • 11
  • 27
  • that bcz you are operating on _factory.getInstance() returns a new instance which is not assigned back to _factory instance – mhasan Nov 01 '16 at 06:04

4 Answers4

1

Your first code TupleFactory.getInstance() is calling a static class method on the class itself, as might be expected for a Singleton pattern implementation.

Calling instance method without an instance

Your second code _factory.getInstance() is calling on an instance variable, a class member which is defined but not yet instantiated. You cannot call an object method on an object that does not exist.

Enum as Singleton

Lastly, the best safest simplest way to implement the Singleton pattern in Java is through an enum. Search Stack Overflow and/or a search-engine for words such as : Java singleton enum Joshua Bloch "Effective Java".

public enum TupleFactory {
    INSTANCE;

    // Add private constructor if needed.

    public Tuple makeTuple( … ) {
        …
        return tuple ;
    }

}

Using this is simple.

Tuple t = TupleFactory.INSTANCE.makeTuple( … ) ;

Beware of misuse of Singleton

Lastly, I'll add the obligatory caution about Singleton often being a “code smell”, a symptom of poor design stemming from a lack of understanding of Object-Oriented Programming.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
0

you have to store _factory.getInstance(); output first as Tupleinstanceclass obj= _factory.getInstance(); return obj.newTuple(Arrays.asList(o1, o2, o3));

0

I think you should change to

public class MyUDF {
...
TupleFactory _factory;

public Tuple func(Tuple input) {
    _factory = TupleFactory.getInstance();
    return _factory.newTuple(Arrays.asList(o1, o2, o3));
}
}
SawDouma
  • 11
  • 4
0

From your first piece of code, I can infer that the getInstance() method is static. The important point to note about static methods is that you shouldn't access them using Class objects. Instead, you should access them using Class name because they're class methods.

The basic idea behind using singletons is that you initially don't have the object of the class and you're calling a class method (not an instance method) to get the object of that class. Now your first piece of code justifies it but in second part of code, you already have _factory object, so why would you call getInstance() to get the object of the class.

Also in this line _factory.getInstance(), note that _factory have just been declared but was never initialized, and that's the reason why you're getting NullPointerException.

Also see :

  1. What is the difference between class and instance methods?
  2. Java: when to use static methods

The following code will work.

public class MyUDF {
    TupleFactory _factory;

    public Tuple func(Tuple input) {
        _factory = TupleFactory.getInstance();
        return _factory.newTuple(Arrays.asList(o1, o2, o3));
    }
}
Community
  • 1
  • 1
Raman Sahasi
  • 30,180
  • 9
  • 58
  • 71
  • I believe your statement "you can't access them using Class objects" should be changed to "you should not access them using Class objects" – mhasan Nov 01 '16 at 06:08