How-to create a static java API? - java

I saw someone writing a java LOG API like the code unerneath.
The idea is that the Client does not have to invoke LogUtil.getInstance() every time.
But my feelings are this is not idiomatic java?
public class LogUtil{
private static LogUtil instance;
private Object current;//some Logger
private static LogUtil getInstance(){
if(instance == null){
instance = new LogUtil();
}
return instance;
}
private static void debug(String text){
}
public static LogUtil init(){
//dosomething with
// getInstance().current;
return getInstance();
}
public static LogUtil logSomething(String text){
//dosomething with
// getInstance().current;
return getInstance();
}
public static LogUtil anotherMethod(String text){
//dosomething with
// getInstance().current;
return getInstance();
}
}
What are the arguments against such a design (making every method static)?

This is basically a variant of "global variables" and the problem is always the same: You can have only one of them. If you ever need to replace or extend this, lot of code will break.
Which why other logging frameworks use factories:
private final static Logger log = LoggerFactory.getLogger( Foo.class );
That way, I have a single global variable (instead of dozens in your case). It's not ideal but give me at least a single point of failure.
This approach allows me to extend / replace the Logger interface with almost anything without having to change hundreds of places in my code.
That said: Don't write your own logging API. Use slf4j. It will take you a bit longer to understand how it works but many clever people have spent years to build a great logging framework that solves thousands of problems that you don't know about, yet.
EDIT
its not ecactly a general loging util. but more a "Reporter class" which produces Business Word documents.
Then have a look at static imports.
I would suggest to expose a single getInstance() method but give that method a more useful name. You can then import this single method statically everywhere else and call it without the LogUtil. prefix.

static classes are Helper classes, for your LogUtil static class i would declare all methods to return void:
public class LogUtil{
private static LogUtil instance = new LogUtil(); //Initialization here
private Object current;//some Logger
private static LogUtil getInstance(){
}
private static void debug(String text){
}
public static void init(){
//dosomething with
// instance.current;
}
public static void logSomething(String text){
//dosomething with
// instance.current;
}
public static LogUtil anotherMethod(String text){
//dosomething with
// instance.current;
}
}
But I'm not comfortable with that design, the use of a LogUtil is to create a Logger depending on configuration preferences, and return it, which have instance methods, like log4j you can have ConsoleLog, FileLog, RemoteLog, etc

Author of this class would probably want to build a fluent interface, explaining why getInstance would be hidden for other class's method calls and explaining the return type not being void.
Benefit of this would allow client to make the method calls cleaner:
LogUtil.init().logSomething("something").anotherMethod("text");
The whole reduced to one line so.
I'm not dealing with the "static" debate, since as Aaron said above, static is often often often not recommended since it breaks flexibility/extensibility and is anti-OO.

One rule-of-thumb for making method static is: ask yourself "does it make sense to call this method, even if no Obj has been constructed yet?" If so, it should definitely be static."
In your example, operations like logSomething(), anotherMethod() are doing something with instance. Since these methods don't make sense without instance, they should be non-static. Only getInstance() method should be static.
Main disadvantage of making everything static is you cannot swap, override or choose method implementations at runtime. This thread has good discussion on disadvantages of static: In Java, is there any disadvantage to static methods on a class?.

Related

is FindBugs 'JLM_JSR166_UTILCONCURRENT_MONITORENTER' safe to ignore in this case

I have a library that I am required to use that has a dangerous initialization of a static value (the classes have been stripped down to the minimum for the example):
public TheirBaseClass {
public static String PathToUse = null;
public BaseClass(){
PathToUse = "Configured";
// ...
// do some other stuff with other side effects
// ...
}
}
I have a case where I attempt to read from the value ConfigValue without instantiating the class (to avoid some of the sideeffects).
Paths.get(TheirBaseClass.PathToUse).toFile()....
This causes a NullPointerException
Because I am required to use this class, I am looking to inherit from it, and attempt to take action to ensure that initialization has taken place when accessing the static.
public MyBaseClass extends TheirBaseClass{
private static final AtomicBoolean isInitialized = new AtomicBoolean(false);
static {
MyBaseClass.Initialize();
}
public static void Initialize(){
// FindBugs does not like me synchronizing on a concurrent object
synchronized(isInitialized){
if( isInitialized.get() ){
return;
}
new TheirBaseClass();
isInitialized.set(true);
}
}
public MyBaseClass(){
super();
}
}
Which allows me to
MyBaseClass.Initialize();
Paths.get(MyBaseClass.PathToUse).toFile()....
This seems to be working reasonably well (and resolves some other phantom defects we've been having). It allows TheirBaseClass to function naturally, while allowing me to safely force initialization in the couple of cases I may need to.
However when I run FindBugs against this code, I get JLM_JSR166_UTILCONCURRENT_MONITORENTER. After reading the description, I agree that the use of AtomicBoolean could be dangerous because someone else could change the value, but...
I think its safe to ignore in this case (but have a doubt)
I generally prefer to rewrite code than put an ignore marker in place
Am I actually doing something dangerous (and just don't see it)? Is there a better way to do this?
Unfortunately, using a different TheirBaseClass is not an option.
Related
Are Java static initializers thread safe?
You might find it easier to adapt the lazy holder idiom:
public MyBaseClass {
private static class Initializer {
static {
new TheirBaseClass();
}
// Doesn't actually do anything; merely provides an expression
// to cause the Initializer class to be loaded.
private static void ensureInitialized() {}
}
{
Initializer.ensureInitialized();
}
// Rest of the class.
}
This uses the fact that class loading happens only once and is synchronized (within a single class loader). It happens only when you instantiate a MyBaseClass.

Initializing static final variable in declaration vs initializing during Application.OnCreate()

I want to store an object state between activities (already considered Parcelables, JSON, yadda yadda) but since I have a couple of Singletons, might as well refer to them in a class that extend Application (modularity + easy to maintain).
So to my question, let's say I have a simple singleton:
class SimpleSingleton
{
private static final SimpleSingleton instance; //The question will refer this line later.
public static SimpleSingleton getInstance()
{
return instance;
}
private SimpleSingleton(){}
}
1: At first I create an initInstance() method within the above class, e.g:
class SimpleSingleton
{
//... the code above
public static void initInstance()
{
if(instance == null) instance = new SimpleSingleton();
}
}
2: Hence the below works, (in which afterwards, I can refer to the singleton from any activity via CustomSingleton.getInstance()):
class MyApp extends Application
{
#Override
public void onCreate()
{
super.onCreate();
initSingletons();
}
protected void initSingletons()
{
SimpleSingleton.initInstance();
}
}
BUT. What if I declare
private static final SimpleSingleton instance = new SimpleSingleton();
instead of
private static final SimpleSingleton instance;
in the SimpleSingleton class?
I assume the object is initialized during compile time, so doesn't that makes the whole #1 and #2 unnecessary? Or do I get the order wrong (especially WHEN the class is actually initialized)? I came from C# and currently developing for Android so this kinda gave me a quick gotcha when I want to refer to my Singletons. Also, I ask this since according to this blog:
The explanation of the weird behavior I saw that makes more sense to me is that the static variables instances are bound to the class loader of the class that first initialized them.
The only difference i can think of is when you do
private static final CustomObject instance = new CustomObject();
when you application is launched it will create and allocate space for it.
Note it might never be used but it would still be using memory.
when you create it on an onCreate method it will only create an instance when it is called.
Using static also has one more disadvantage that is it will use your perm gen space and if by chance it fails to give it space or fails to create it your program will crash on startup. Leaving you confused.
I strongly suggest using the onCreate method approach.

Java/Android: Method with Full Project Scope

I have a method that I've created that I would like to be able to use anywhere, but I don't know what the best practice is for giving access to that method throughout the project. Do I just create a .java file with a public method and that will give access throughout? Will I need to declare it anywhere (somewhere in the manifest?)?
I'm sure this has been asked, but I am not returning anything useful on my google searches. I am not good enough at googling for Android, yet! Sorry for adding to the duplicates, if I am.
You have a few options. The simplest is a public static method.
public class MyClass {
public static MyReturnType myMethod(MyArgumentType input) {
// my code here
}
}
You will now be able to call this like:
MyClass.myMethod(arg);
Use static methods. As for me, if I want to store just methods in the same place I create a new class and all of the methods are static. For example.
public static int parseInt(String str)
{
try
{
return Integer.parseInt(str);
}
catch (NumberFormatException e)
{
return -1;
}
}
If it's just do anything and doesn't require to save state in the class, this is the best solution.
Here's a sample of a static method.
public class Messages {
public static String mySpecialFinalMessage(){
return "Hello Stackoverflow";
}
}
You no longer need to create an Instance of Messages to call mySpecialFinalMessage() because it is a static. The best practice to call a static method is in this format CLASSNAME.STATICMETHODNAME();
So in our example,
Messages.mySpecialFinalMessage()
Please Note that you calling static methods inside non-static method is legal however, calling non-static methods inside static methods will give you a compile time error.
this is legal
public class MyMessage {
public String getMessage(){
return Messages.mySpecialFinalMessage();
}
}
Take note taht Messages.mySpecialFinalMessage() is that static method. Also, Notice that we did not create an instance of Messages to call mySpecialFinalMessage(), rather we've just called it directly by CLASSNAME.STATICMETHODNAME

How to Return an Object Via Static Factory Methods?

I know Java basics, and now I'm in the journey of reading Effective Java. The book suggest using static factory methods instead of constructors. So I have Groovy code like this:
public class Anto {
public static void main(String[] args) {
println Java.javaInstance()
}
}
class Java {
public static Java javaInstance() {
return this
}
}
When I compile this, I get an error like this:
Caught: org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object 'class Java' with class 'java.lang.Class' to class 'Java'
org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object 'class Java' with class 'java.lang.Class' to class 'Java'
at Java.javaInstance(Anto.groovy:9)
at Java$javaInstance.call(Unknown Source)
at Anto.main(Anto.groovy:3)
Where am I making a mistake?
You can do it using return new Java();. Static methods don't have access to this.
EDIT:
These static factories are usually singletons, which means that only one instance of the class should be used (typically, a connection to a db for example). If you want do add this dimension to your Java class, use a private static attribute as follow:
class Java {
private static Java instance;
public static Java javaInstance() {
if(instance == null) {
instance = new Java();
}
return instance;
}
}
Creating a Singleton correctly can be easy to get wrong (especially in a multi-threaded environment), so you're probably better using the Singleton annotation that comes with Groovy rather than rolling your own:
public class Anto {
public static void main(String[] args) {
println Java.instance
}
}
#Singleton
class Java {
}
This transforms the Java class to:
class Java {
private static volatile Java instance
private Java() {}
static Java getInstance () {
if( instance ) {
instance
} else {
synchronized( Java ) {
if( instance ) {
instance
} else {
instance = new Java()
}
}
}
}
}
A good (albeit not specific to Groovy) example of a library that uses static factory methods that you could look at would be Google Guava. Guava uses this idiom in a number of places. For example, their Range class supports nine types of ranges, and if they used normal constructors, their signatures would conflict in several cases since the only thing you can use to distinguish them is their arguments.
Static methods on the other hand can also be distinguished by their name, so Guava defines different ones for each type of Range. Internally these methods still call a normal constructor, but it's not one that's publicly accessible.
import com.google.common.collect.Ranges
import com.google.common.collect.DiscreteDomains
final dom = DiscreteDomains.integers()
assert [1,2,3,4,5] as Set == Ranges.closed(1, 5).asSet(dom)
assert [2,3,4] as Set == Ranges.open(1, 5).asSet(dom)
This is a useful idiom, but not one that should just be automatically preferred over a normal constructor. In situations where a normal constructor would have sufficed, you've at best written more code than you needed and at worst have made extending the class impossible, since any subclasses will still need a public or protected constructor they can call.
You can't use this because static methods are not instance methods.
Each time you create a new instance of a particular class, that new object/instance as it's own state. this points to a particular instance.
Are you trying to make a singleton ? Meaning you just want a single instance of a class ?
class Singleton {
//static reference to a particular instance
private static Singleton instance;
//private constructor so that it cant be called outside this class scope
private Singleton();
//synchronized in case your working in threaded enviroment
public synchronized static Singleton getInstance()
{
if(NULL == instance)
{
instance = new Singleton();
}
return instance;
}
}

Pass argument to a static constructor in Java?

I'm trying to initialize a static class, with an argument, and then run some more static code in that class.
I'm aware of the static block, but it seems it can't take any arguments.
Is there a way to pass arguments to a static constructor?
If not, what is the recommended technique to initialize a Static class using an argument?
Edit:
A static class to my understanding is a class which cannot be instantiated (in c# they're called static classes, if Java has a different term for them, sorry for not being aware of it) - it's accessed through it's class name rather than an object name.
What I'm trying to achieve (very simplified) is a class which receives a dictionary as String, parses it, and has methods manipulate it like GetRandomEntry.
Here's an elaborated snippet of my code:
public class QuestionsRepository {
private static Map<String,String[]> easyDefinitions = new HashMap<String,String[]>();
//...
staticĀ 
{
// need to receive and parse dictionary here
}
//...
Taking the relevant parts of a code snippet is never easy, hope i have chosen wisely (:
Another detail that may be relevant - I'm a c# programmer, usually. Just Started learning Java lately.
Thanks.
I think you would need to initialize the static fields of the class according to some input. You can do it in the following way by calling the static method of another class:
class ClassToInitialize {
static {
staticField = ParamPassClass.getParameter();
}
private static String staticField;
ClassToInitialize() {
System.out.println("This is the parameter: " + staticField);
}
}
class ParamPassClass {
private static String parameter;
static String getParameter() {
return parameter;
}
static void setParameter(String parameter) {
ParamPassClass.parameter = parameter;
}
}
class Main {
public static void main(String args[]) {
ParamPassClass.setParameter("Test param");
new ClassToInitialize();
}
}
Java doesn't have static constructors. It only has static initializers and static initializers do not take any arguments. It is executed when the class is first loaded, and there is no way to call it yourself.
You either need to use actual objects, or add some way of configuring the class (eg through a static method).
you should mention the member class with a static qualifier, otherwise there is no such a thing as a static class
Here you can find the explanation of using the word 'static' in this context.
Now you should just call its constructor and pass all the arguments you want,
the only restriction that you have on a static member class is that it can't refer the non-static fields of its outer class, it resembles a static methods on class that can't refer the non-static fields of class.
I didn't understand why do you mention a static initialization block here, could you please clarify a little?
Be aware also that in java there is no such a thing as static constructor....
Hope this helps
You can have a static method public static void setUp(Arg1 arg1, Arg2 arg2...) which sets up all your static fields and invoke it when your program starts.
You have to make sure this method will be called only once [or only when you want to reset these fields]
It is not possible to pass arguments directly to the static initializes (JLS:static initializers).
It would be nice if you could share more information about your goals.
You could use an enum to initialize a singleton with a string parameter like this
import java.util.*;
class Data {
static Map<String,String[]> easyDefinitions = new HashMap<String,String[]>();
}
public enum QuestionsRepository
{
repository("primary=red,green,blue;secondary=cyan,yellow,magenta");
QuestionsRepository(String dictionary) {
String[] rules = dictionary.split(";");
for (String rule:rules) {
String[] keyValuePair = rule.split("=",2);
Data.easyDefinitions.put(keyValuePair[0],keyValuePair[1].split(","));
}
}
}

Categories

Resources