I'm trying to write an expression or series of statements of Java source code that when written inside a static method evaluates to null, but if the method is non-static evaluates to this.
My initial idea was to 'overload' on static vs non-static, as below:
public class test {
public void method1() {
System.out.println(getThisOrNull());
}
public static void method2() {
System.out.println(getThisOrNull());
}
private static Object getThisOrNull() {
return null;
}
private Object getThisOrNull() {
return this;
}
public static void main(String[] args) {
test t = new test();
System.out.println(t);
t.method1();
t.method2();
}
}
Unfortunately this isn't actually legal Java, you can't 'overload' like that and it just gives a compiler error:
test.java:14: error: method getThisOrNull() is already defined in class test
private Object getThisOrNull() {
^
1 error
Clearly in an ideal world I wouldn't write it like that to begin with, but the problem is this code will be generated automatically by a tool that is not really semantically or syntactically enough to distinguish between the static vs non-static case.
So, how can I write some source code that, although byte for byte identical compiles and behaves differently in depending on the presence of the static modifier for the method?
This can be achieved with a trick and a bit of help from Java's reflection facilities. It's ugly, but it works:
import java.lang.reflect.Field;
public class test {
public void method1() {
System.out.println(getThisOrNull(new Object(){}));
}
public static void method2() {
System.out.println(getThisOrNull(new Object(){}));
}
private static Object getThisOrNull(final Object o) {
for (Field f: o.getClass().getDeclaredFields()) {
if (f.getType().equals(test.class)) {
try {
return f.get(o);
}
catch (IllegalAccessException e) {
// Omm nom nom...
}
}
}
return null;
}
public static void main(String[] args) {
test t = new test();
System.out.println(t);
t.method1();
t.method2();
}
}
This compiles and runs as hoped for:
test#183f74d
test#183f74d
null
The trick that makes this possible is the use of new Object(){}, which creates a new, anonymous class within the existing method that we're trying to figure out if it's static or not. The behaviour of this is subtly different between the two cases.
If the goal were just to figure out if the method is static or not we could write:
java.lang.reflect.Modifiers.isStatic(new Object(){}.getClass().getEnclosingMethod().getModifiers())
Since we want to get this (when available) we need to do something slightly different. Fortunately for us classes defined within the context of an instance of an object in Java get an implicit reference to the class that contains them. (Normally you'd access it with test.this syntax). We needed a way to access test.this if it existed, except we can't actually write test.this anywhere because it too would be syntactically invalid in the static case. It does however exist within the object, as a private member variable. This means that we can find it with reflection, which is what the getThisOrNull static method does with the local anonymous type.
The downside is that we create an anonymous class in every method we use this trick and it probably adds overheads, but if you're backed into a corner and looking for a way of doing this it does at least work.
It's a common practice to encapsulate code that often changes. In fact, it is often in the form of using an object to delegate the varying logic to. A sample would be the following:
public class SampleClass {
Object obj = new ObjectWithVaryingMethod();
public SampleClass(Object obj){
this.obj=obj;
}
public String getString(){
return obj.toString();
}
public static void main(String args[]){
SampleClass sampleClass=new SampleClass(new ObjectWithVaryingMethod());
System.out.println(sampleClass.getString());
}
}
class ObjectWithVaryingMethod{
#Override
public String toString(){
return "Hi";
}
}
Can you suggest what problems I may encounter when "encapsulation" is done on what doesn't vary? I find it to be a good coding conduct when the main class itself is the one that is often subject to change or improvement. A sample would be the following. In this second case, retrieving "Hi", which is the part that doesn't vary, was "encapsulated" in another class.
public class SampleVaryingClass {
public static void main(String args[]) {
//here I may opt to print getHi's value on sysout or on a dialog
System.out.println(ObjectWithNonVaryingMethod.getHi());
}
}
In a completely different class...
public class ObjectWithNonVaryingMethod {
private static final String hi = "Hi";
//"Hi" should always be returned
public static String getHi() {
return hi;
}
}
Can you give some pro's and con's on doing this?
Both code cannot be compared each other. One is static, another one isn't. I hope you understand the concept of encapsulating the object in the first code. Here is the pros and cons for the second one. Remember that static is "generally" bad, and do not support concurrency by default.
pros:
With getHi, you are keeping the string field private, meaning that it cannot be set from other source
Say that you need to do setHi from other source, you can add several guard clauses for it. This is called defensive programming.
public static setHi(String input){
if(input == null) { input = ""; } // can throw exception instead
hi = input;
}
cons:
It is static, needless to say
You don't get any advantage other than guard clauses. If your class is not static, you can swap it with other class implementing same interface, or other class inherited from that class.
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(","));
}
}
}
What is the difference between ClassName.m() and (new ClassName()).m() m() is a static method.
The difference is that in your second example you are creating an unnecessary object in memory.
It is still calling the same static method for the ClassName class.
It is recommended to use ClassName.m() to avoid unnecessary object creation and to provide context to the developers indicating that a static method is indeed being called.
Three things:
The second has an extra call, which means it might change the outcome. This may be bad, may not, but it is something to consider. See example on how this can work.
The second creates an extra object. That's bad.
The second implies you're calling a method on an object, not on the class itself, which confuses people who read it. That's also bad. See example for how this can be very bad!
Consider the following, reason 1:
class ClassName {
static int nextId;
static int m() { return nextId; }
int id;
ClassName() { id = nextId; nextId++; }
/**
C:\junk>java ClassName
2
2
3
*/
public static void main(String[] args) {
new ClassName();
new ClassName();
System.out.println(ClassName.m());
System.out.println(ClassName.m());
System.out.println((new ClassName()).m());
}
}
Consider the following, adding on to reason 2, as alluded to by #emory:
class ClassName {
// perhaps ClassName has some caching mechanism?
static final List<ClassName> badStructure = new LinkedList<ClassName>();
ClassName() {
// Note this also gives outside threads access to this object
// before it is fully constructed! Generally bad...
badStructure.add(this);
}
public static void main(String[] args) {
ClassName c1 = new ClassName(); // create a ClassName object
c1 = null; // normally it would get GC'd but a ref exist in badStructure! :-(
}
}
Consider the following, reason 3:
class BadSleep implements Runnable {
int i = 0;
public void run() {
while(true) {
i++;
}
}
public static void main(String[] args) throws Exception {
Thread t = new Thread(new BadSleep());
t.start();
// okay t is running - let's pause it for a second
t.sleep(1000); // oh snap! Doesn't pause t, it pauses main! Ugh!
}
}
From an external observer's perspective, there's no difference. Both ways result in a call to the method which can only do the exact same thing in either case. You should never do the second one, though, as it just doesn't make sense to create an object in that case.
If m() is a static method, it's generally correct practice to use ClassName.m() since m() is a method of ClassName, not an object of ClassName.
As far as I understood the "static initialization block" is used to set values of static field if it cannot be done in one line.
But I do not understand why we need a special block for that. For example we declare a field as static (without a value assignment). And then write several lines of the code which generate and assign a value to the above declared static field.
Why do we need this lines in a special block like: static {...}?
The non-static block:
{
// Do Something...
}
Gets called every time an instance of the class is constructed. The static block only gets called once, when the class itself is initialized, no matter how many objects of that type you create.
Example:
public class Test {
static{
System.out.println("Static");
}
{
System.out.println("Non-static block");
}
public static void main(String[] args) {
Test t = new Test();
Test t2 = new Test();
}
}
This prints:
Static
Non-static block
Non-static block
If they weren't in a static initialization block, where would they be? How would you declare a variable which was only meant to be local for the purposes of initialization, and distinguish it from a field? For example, how would you want to write:
public class Foo {
private static final int widgets;
static {
int first = Widgets.getFirstCount();
int second = Widgets.getSecondCount();
// Imagine more complex logic here which really used first/second
widgets = first + second;
}
}
If first and second weren't in a block, they'd look like fields. If they were in a block without static in front of it, that would count as an instance initialization block instead of a static initialization block, so it would be executed once per constructed instance rather than once in total.
Now in this particular case, you could use a static method instead:
public class Foo {
private static final int widgets = getWidgets();
static int getWidgets() {
int first = Widgets.getFirstCount();
int second = Widgets.getSecondCount();
// Imagine more complex logic here which really used first/second
return first + second;
}
}
... but that doesn't work when there are multiple variables you wish to assign within the same block, or none (e.g. if you just want to log something - or maybe initialize a native library).
Here's an example:
private static final HashMap<String, String> MAP = new HashMap<String, String>();
static {
MAP.put("banana", "honey");
MAP.put("peanut butter", "jelly");
MAP.put("rice", "beans");
}
The code in the "static" section(s) will be executed at class load time, before any instances of the class are constructed (and before any static methods are called from elsewhere). That way you can make sure that the class resources are all ready to use.
It's also possible to have non-static initializer blocks. Those act like extensions to the set of constructor methods defined for the class. They look just like static initializer blocks, except the keyword "static" is left off.
It's also useful when you actually don't want to assign the value to anything, such as loading some class only once during runtime.
E.g.
static {
try {
Class.forName("com.example.jdbc.Driver");
} catch (ClassNotFoundException e) {
throw new ExceptionInInitializerError("Cannot load JDBC driver.", e);
}
}
Hey, there's another benefit, you can use it to handle exceptions. Imagine that getStuff() here throws an Exception which really belongs in a catch block:
private static Object stuff = getStuff(); // Won't compile: unhandled exception.
then a static initializer is useful here. You can handle the exception there.
Another example is to do stuff afterwards which can't be done during assigning:
private static Properties config = new Properties();
static {
try {
config.load(Thread.currentThread().getClassLoader().getResourceAsStream("config.properties");
} catch (IOException e) {
throw new ExceptionInInitializerError("Cannot load properties file.", e);
}
}
To come back to the JDBC driver example, any decent JDBC driver itself also makes use of the static initializer to register itself in the DriverManager. Also see this and this answer.
I would say static block is just syntactic sugar. There is nothing you could do with static block and not with anything else.
To re-use some examples posted here.
This piece of code could be re-written without using static initialiser.
Method #1: With static
private static final HashMap<String, String> MAP;
static {
MAP.put("banana", "honey");
MAP.put("peanut butter", "jelly");
MAP.put("rice", "beans");
}
Method #2: Without static
private static final HashMap<String, String> MAP = getMap();
private static HashMap<String, String> getMap()
{
HashMap<String, String> ret = new HashMap<>();
ret.put("banana", "honey");
ret.put("peanut butter", "jelly");
ret.put("rice", "beans");
return ret;
}
There are a few actual reasons that it is required to exist:
initializing static final members whose initialization might throw an exception
initializing static final members with calculated values
People tend to use static {} blocks as a convenient way to initialize things that the class depends on within the runtime as well - such as ensuring that particular class is loaded (e.g., JDBC drivers). That can be done in other ways; however, the two things that I mention above can only be done with a construct like the static {} block.
You can execute bits of code once for a class before an object is constructed in the static blocks.
E.g.
class A {
static int var1 = 6;
static int var2 = 9;
static int var3;
static long var4;
static Date date1;
static Date date2;
static {
date1 = new Date();
for(int cnt = 0; cnt < var2; cnt++){
var3 += var1;
}
System.out.println("End first static init: " + new Date());
}
}
It is a common misconception to think that a static block has only access to static fields. For this I would like to show below piece of code that I quite often use in real-life projects (copied partially from another answer in a slightly different context):
public enum Language {
ENGLISH("eng", "en", "en_GB", "en_US"),
GERMAN("de", "ge"),
CROATIAN("hr", "cro"),
RUSSIAN("ru"),
BELGIAN("be",";-)");
static final private Map<String,Language> ALIAS_MAP = new HashMap<String,Language>();
static {
for (Language l:Language.values()) {
// ignoring the case by normalizing to uppercase
ALIAS_MAP.put(l.name().toUpperCase(),l);
for (String alias:l.aliases) ALIAS_MAP.put(alias.toUpperCase(),l);
}
}
static public boolean has(String value) {
// ignoring the case by normalizing to uppercase
return ALIAS_MAP.containsKey(value.toUpper());
}
static public Language fromString(String value) {
if (value == null) throw new NullPointerException("alias null");
Language l = ALIAS_MAP.get(value);
if (l == null) throw new IllegalArgumentException("Not an alias: "+value);
return l;
}
private List<String> aliases;
private Language(String... aliases) {
this.aliases = Arrays.asList(aliases);
}
}
Here the initializer is used to maintain an index (ALIAS_MAP), to map a set of aliases back to the original enum type. It is intended as an extension to the built-in valueOf method provided by the Enum itself.
As you can see, the static initializer accesses even the private field aliases. It is important to understand that the static block already has access to the Enum value instances (e.g. ENGLISH). This is because the order of initialization and execution in the case of Enum types, just as if the static private fields have been initialized with instances before the static blocks have been called:
The Enum constants which are implicit static fields. This requires the Enum constructor and instance blocks, and instance initialization to occur first as well.
static block and initialization of static fields in the order of occurrence.
This out-of-order initialization (constructor before static block) is important to note. It also happens when we initialize static fields with the instances similarly to a Singleton (simplifications made):
public class Foo {
static { System.out.println("Static Block 1"); }
public static final Foo FOO = new Foo();
static { System.out.println("Static Block 2"); }
public Foo() { System.out.println("Constructor"); }
static public void main(String p[]) {
System.out.println("In Main");
new Foo();
}
}
What we see is the following output:
Static Block 1
Constructor
Static Block 2
In Main
Constructor
Clear is that the static initialization actually can happen before the constructor, and even after:
Simply accessing Foo in the main method, causes the class to be loaded and the static initialization to start. But as part of the Static initialization we again call the constructors for the static fields, after which it resumes static initialization, and completes the constructor called from within the main method. Rather complex situation for which I hope that in normal coding we would not have to deal with.
For more info on this see the book "Effective Java".
So you have a static field (it's also called "class variable" because it belongs to the class rather than to an instance of the class; in other words it's associated with the class rather than with any object) and you want to initialize it. So if you do NOT want to create an instance of this class and you want to manipulate this static field, you can do it in three ways:
1- Just initialize it when you declare the variable:
static int x = 3;
2- Have a static initializing block:
static int x;
static {
x=3;
}
3- Have a class method (static method) that accesses the class variable and initializes it:
this is the alternative to the above static block; you can write a private static method:
public static int x=initializeX();
private static int initializeX(){
return 3;
}
Now why would you use static initializing block instead of static methods?
It's really up to what you need in your program. But you have to know that static initializing block is called once and the only advantage of the class method is that they can be reused later if you need to reinitialize the class variable.
let's say you have a complex array in your program. You initialize it (using for loop for example) and then the values in this array will change throughout the program but then at some point you want to reinitialize it (go back to the initial value). In this case you can call the private static method. In case you do not need in your program to reinitialize the values, you can just use the static block and no need for a static method since you're not gonna use it later in the program.
Note: the static blocks are called in the order they appear in the code.
Example 1:
class A{
public static int a =f();
// this is a static method
private static int f(){
return 3;
}
// this is a static block
static {
a=5;
}
public static void main(String args[]) {
// As I mentioned, you do not need to create an instance of the class to use the class variable
System.out.print(A.a); // this will print 5
}
}
Example 2:
class A{
static {
a=5;
}
public static int a =f();
private static int f(){
return 3;
}
public static void main(String args[]) {
System.out.print(A.a); // this will print 3
}
}
If your static variables need to be set at runtime then a static {...} block is very helpful.
For example, if you need to set the static member to a value which is stored in a config file or database.
Also useful when you want to add values to a static Map member as you can't add these values in the initial member declaration.
It is important to understand that classes are instantiated from java.class.Class during runtime. That is when static blocks are executed, which allows you to execute code without instantiating a class:
public class Main {
private static int myInt;
static {
myInt = 1;
System.out.println("myInt is 1");
}
// needed only to run this class
public static void main(String[] args) {
}
}
The result is myInt is 1 printed to the console.
As supplementary, like #Pointy said
The code in the "static" section(s) will be executed at class load
time, before any instances of the class are constructed (and before
any static methods are called from elsewhere).
It's supposed to add System.loadLibrary("I_am_native_library") into static block.
static{
System.loadLibrary("I_am_a_library");
}
It will guarantee no native method be called before the related library is loaded into memory.
According to loadLibrary from oracle:
If this method is called more than once with the same library name,
the second and subsequent calls are ignored.
So quite unexpectedly, putting System.loadLibrary is not used to avoid library be loaded multi-times.
static block is used for any technology to initialize static data member in dynamic way,or we can say for the dynamic initialization of static data member static block is being used..Because for non static data member initialization we have constructor but we do not have any place where we can dynamically initialize static data member
Eg:-class Solution{
// static int x=10;
static int x;
static{
try{
x=System.out.println();
}
catch(Exception e){}
}
}
class Solution1{
public static void main(String a[]){
System.out.println(Solution.x);
}
}
Now my static int x will initialize dynamically ..Bcoz when compiler will go to Solution.x it will load Solution Class and static block load at class loading time..So we can able to dynamically initialize that static data member..
}
static int B,H;
static boolean flag = true;
static{
Scanner scan = new Scanner(System.in);
B = scan.nextInt();
scan.nextLine();
H = scan.nextInt();
if(B < 0 || H < 0){
flag = false;
System.out.println("java.lang.Exception: Breadth and height must be positive");
}
}