Consider the following Java class:
public class Foo
{
public static void doStuff()
{
// boring stuff here
}
}
Is it possible to access either the class literal Foo.class, or just the class name "Foo" from within a static method such as doStuff()? In a non-static method I would just call this.getClass(), but there is no this to use in a static method.
Edit: sorry this wasn't clear - I want to do this with explicitly using the class literal Foo.class.
Use Class<Foo> clazz = Foo.class
If you need something like:
class Foo {
static Class foo(){return the current class}
}
class Bar extends Foo {
}
and expect Bar.foo() to return Bar if called on Bar, and Foo if called on Foo - you have something wrong in your design and perhaps you need to make the methods non-static.
Unfortunately Java doesn't give you a good way to do this. You just have to reference Foo.class. This is something that is a regular annoyance for me.
For logging I solved it (the idea for the solution came from Log5j) by reading the stack, because it got really annoying to restate the class for every logger every time. Fortunately modern IDEs make it relatively painless, so that refactoring isn't really negatively impacted if you have to change the name of the class.
EDIT: Some code:
private static StackTraceElement getCallerStackTraceElement(StackTraceElement[] elements) {
for (int i = 0; i < elements.length; i++) {
if (elements[i].getClassName().equals(MyLogger.class.getName())) {
return elements[i + 1];
}
}
return null;
}
MyLogger in this case is the class where this method exists. It finds itself in the stacktrace and goes one earlier, and then extracts the class from the StackTraceElement.
The StackTraceElement[] array can be retrieved by either new Exception().getStackTrace(), or Thread.currentThread().getStackTrace(); The way this method is written it assumes the stacktrace is created on the first method call into MyLogger.
Just use Foo.class. You don't have to worry about inheritance or anything like that, since there's no object associated with a static method.
When dealing with static methods, you can think of them as libraries, where the class name becomes the library name. You tell the compiler which bar() method to run by specifying the library (class) name. Foo.bar() vs. Bar.bar().
The method itself has no parent and no instance, therefore, it can't use reflection to know what class it's part of. However, you can add a reflection method.
You can add a static method to the class that answers itself what class it's in:
public class Foo {
private static class self() {
return Foo.class;
}
public static void doStuff()
{
// Use self() to reference the Foo class
}
}
Notice that I made the self() method private because outside of the class, it makes no sense.
This works because the self() method is visible from inside the class, and inside the static method.
In contrast, PHP has a self construct to reference the current class.
Related
I have the following class:
public class Foo(){
int parameter;
static Set<Foo> cache=new HashSet<Foo>();
public Foo(int parameter){
this.parameter=parameter;
addToCache(this);
}
public static Foo Factory(int parameter){
Foo duplicate=findDuplicate(parameter);
if (duplicate!=null){
return duplicate;
}else{
return new Foo(parameter);
}
}
}
Notice that calling Foo's constructor directly will add to the static cache.
I now need to subclass this object to add some functionality.
public class Bar() extends Foo{
public Bar(int parameter){
//Danger
}
}
But now I'm stuck. Bar's constructor has to call super() one way or another, but that won't check for duplicates like Foo.Factory() does.
What I would really like would be something like:
public Bar(int parameter){
this=Foo.Factory(parameter);
}
But that's obviously not valid java.
For now, I have been forced to write a hacky secondary constructor for Foo that also checks for duplicates, and have Bar use that:
//Second unused parameter just so the constructors are different
public Foo(int parameter, boolean isEvil){
Foo duplicate= findDuplicate(parameter);
if (duplicate!=null){
this.copy(duplicate); //Evilly take on all attributes of duplicate
}else{
//Now we have to copy the body of the original constructor.
//It has to be kept synched forever, and I can't even call it!
this.parameter=parameter;
addToCache(this);
}
}
Bar(int parameter){
super(int,true);
}
But this has the problem of always creating a new object, which can cause mutability and hashing concerns. Furthermore, anyone not paying attention won't be able to tell that this constructor works differently.
TLDR: How do I make a constructor for a class whose super should only be made via a factory method.
Possible duplicate of this question, but in java (also that question had only one answer and it was unsatisfying to both me and OP)
The way I see it, you have two options.
Options 1 is to create a factory method for bar instead of a public constructor.
Option 2 is that, instead of making bar inherit from foo, it instead contains an instance of foo as a member. In the constructor you can call the factory method for foo.
Which way you go probably depends on the details.
I ran into an interesting problem yesterday and while the fix was quite simple, I'm still a bit fuzzy on the "why" of it.
I have a class that has a private member variable that is assigned when it is instantiated, however if it is used in an abstract function that is called by the super class's constructor, the variable does not have a value. The solution to the problem was quite simple, I simply had to declare the variable as static and it was assigned correctly. Some code to illustrate the problem:
class Foo extends BaseClass
{
private final String bar = "fooBar!";
public Foo()
{
super();
}
#Override
public void initialize()
{
System.out.println(bar);
}
}
And the base class:
abstract class BaseClass
{
public BaseClass()
{
initialize();
}
public abstract void initialize();
}
In this example, when we call new Foo(); it will output (null) instead of the expected fooBar!
Since we're instantiated an object of type Foo, should its members not be allocated and assigned prior to calling its (and consequently its super class's) constructor? Is this specified somewhere in the Java language or is it JVM specific?
Thanks for any insight!
The assignment of bar = "fooBar!"; is inlined into the constructor during compile time.
The superclass constructor runs before the subclass constructor, hence it would only be natural that the statement is executed afterwards.
Generally though, it's bad practice to call overridable methods from a constructor.
It is as defined by the Java Language Specification. Changing it to static will almost never be and acceptable solution in real world situation.
See JLS 4.12.5 Initial Values of Variablesand JLS 8.3.2 Initialization of Fields
Overall, it is bad practice to call a non-final method from a constructor. the reason being that it could (and if the method is abstract then definitely does) call method in the class that has not yet been initialized: When new Foo() is executed, the BaseClass initializer (constructor) gets called before the Foo constructor, so Foo.initialize is essentially working on an Object that has not been fully constructed yet.
There's just one thing I would like to add to the accepted answer, because I don't entirely agree with his conclusion.
We've all done this.
class Engine {
public Engine() {
init();
}
void init() {
lockDoors();
releasePressure();
tightenSeatbelts();
launchRocket();
}
...
}
Now the question is, which access modifier should we add to our init() function. Should it be private or protected.
make it private <-- keeps subclasses out
make it protected <-- allows subclasses in
Before you make a choice
Now first of all, you should realize that (almost) all code in the Engine class can be replaced by a subclass.
code in a public function, can easily be overridden
code in a protected function, can easily be overridden
code in a private function, can be replaced by overriding all methods that call it.
Well, there is just one exception:
you can never modify the code of a constructor
you can never avoid a private method being called from the constructor of a super class.
(and of course, you cannot replace a final method)
Protected init() - the wrong way
Let's say the init() method is protected there is indeed a pitfall. It is tempting to override it to add features as follows. That would indeed be a mistake.
class SubEngine extends Engine {
int screws = 5;
void init() {
tightenScrews();
super.init();
}
void tightenScrews() {
// this won't print 5, but it will print 0.
System.out.println("tightening " + screws + " screws");
}
}
Protected init() - the right way
So, basically, you should just disable the parents code and postpone execution to your own constructor instead.
class SubEngine extends Engine {
int screws = 5;
public SubEngine() {
initSubEngine();
}
void init() {
// disable parent code
}
void initSubEngine() {
tightenScrews();
super.init();
}
void tightenScrews() {
// this will print 5 as expected
System.out.println("tightening " + screws + " screws");
}
}
Private init() - you may need a phonecall
Now, what if the init() method is private ?
Like mentioned above, there is no way to disable the code of a parent constructor. And if init() is private you simply cannot disable it.
You'll end up copying the entire Engine class, perhaps just to add 1 line of code.
And that may not be the end of it. Even after copying your class, your copied object won't be an Engine meaning that you won't be able to use your EngineUtil#inspectEngine(Engine engine) function.
Perhaps somebody knew this in advance and made an IEngine interface. Then you can get away with it.
In practice it means you'll have to take your phone, and call to that other department that made the Engine class, and ask them to change their code a little to take away some restrictions.
Intelligent design
There is another way. Constructors are for setting variables. They shouldn't activate anything. Everytime you see a class creating a new Thread from their constructor (or through a private method) that should be a red flag.
class Engine {
public Engine() {
}
public void init() {
lockDoors();
releasePressure();
tightenSeatbelts();
launchRocket();
}
// and you probably also want one of these
public void shutdown() { ... }
...
}
Intention
Of course, your intention may very well be not to open up your code. Perhaps you really don't want to allow others to extend your classes. There certainly can be cases where you want to lock people out.
Be aware that it will also make it harder to write tests for your code.
Anyway that's a different scenario.
I have two classes defined like this:
class A {
public static String getName(){
Class c = getCalledClass();
return c.getSimpleName();
}
}
class B extends A {
//no methods are defined here!
}
I want to know if it is possible to compose the static method getCalledClass() such that calling A.getName() will return A and B.getName() will return B?
Thanks.
This is not possible, at least not in the general sense that you've asked.
There is no method B.getName(). While you can type that in code, it will be compiled to identical bytecode to A.getName() (and I think you get a compiler warning too).
Thus at runtime, there is no way to tell how someone referenced the static method - just as there's no way to tell what local variable names a caller is using.
I don't know if you can remove static or not as per your requirement. If you can remove static and use polymorphism then you can get what you want. Below is the code example I tested.
class A {
public String getName(){
Class c = this.getCalledClass();
return c.getSimpleName();
}
Class getCalledClass() {
return A.class;
}
}
class B extends A {
Class getCalledClass() {
return B.class;
}
}
class TestApplication {
public static void main(String[] args) {
A objA = new A();
System.out.println(objA.getName());
A objB = new B();
System.out.println(objB.getName());
}
}
When the javac compiler finds a call to B.getName(), it resolves it there-and-then to A.getName() and puts a static call to A.getName() in the byte code.
There does not exist any mechanism in java which can deduce the form used in the source code from the byte code.
If you want B.getName() to be a different method to A.getName(), you have to define a method called getName() in B. Since in that method the called class will always be 'B', there's no need to mess around with the stack trace or other mechanisms. However, generally if you think it matters what was before the dot, there's probably a better object oriented design for you to use instead.
The stack trace will contain only the name of the class that that static method is defined on. Even if you call B.method(), you'll see A.method() in the stack trace. Using the static scheme you cannot extract reliably the info you want.
If you use non-static methods then this will be the instance of the type you are looking for.
public String getName() {
return this.class.getSimpleName();
}
This is a knowledge/curiosity question only.
After several years in Java, this has only just struck me.
class Foo {
class Bar{
Foo.this.doSomething();
}
}
When I look at Foo.this, I would assume that it's a static reference which obviously is not the case.
I know this is part of the Java spec, but exactly what is going on when you use <Class>.this?
Is it one of those "it just is" things?
I know this is part of the Java spec, but exactly what is going on when you use .this?
It just refers to a "hidden" field within Bar. It's easiest to see this by decompiling. You'll see that there's a Bar constructor taking a reference to an instance of Foo. That reference is stored in a field, and then when you use Foo.this, it just accesses that field. So assuming you'd put your Foo.this.doSomething() into a someMethod call, your code is similar to:
class Foo {
static class Bar {
private final Foo $foo;
Bar(Foo foo) {
this.$foo = foo;
}
public void someMethod() {
$foo.doSomething();
}
}
}
I ran into an interesting problem yesterday and while the fix was quite simple, I'm still a bit fuzzy on the "why" of it.
I have a class that has a private member variable that is assigned when it is instantiated, however if it is used in an abstract function that is called by the super class's constructor, the variable does not have a value. The solution to the problem was quite simple, I simply had to declare the variable as static and it was assigned correctly. Some code to illustrate the problem:
class Foo extends BaseClass
{
private final String bar = "fooBar!";
public Foo()
{
super();
}
#Override
public void initialize()
{
System.out.println(bar);
}
}
And the base class:
abstract class BaseClass
{
public BaseClass()
{
initialize();
}
public abstract void initialize();
}
In this example, when we call new Foo(); it will output (null) instead of the expected fooBar!
Since we're instantiated an object of type Foo, should its members not be allocated and assigned prior to calling its (and consequently its super class's) constructor? Is this specified somewhere in the Java language or is it JVM specific?
Thanks for any insight!
The assignment of bar = "fooBar!"; is inlined into the constructor during compile time.
The superclass constructor runs before the subclass constructor, hence it would only be natural that the statement is executed afterwards.
Generally though, it's bad practice to call overridable methods from a constructor.
It is as defined by the Java Language Specification. Changing it to static will almost never be and acceptable solution in real world situation.
See JLS 4.12.5 Initial Values of Variablesand JLS 8.3.2 Initialization of Fields
Overall, it is bad practice to call a non-final method from a constructor. the reason being that it could (and if the method is abstract then definitely does) call method in the class that has not yet been initialized: When new Foo() is executed, the BaseClass initializer (constructor) gets called before the Foo constructor, so Foo.initialize is essentially working on an Object that has not been fully constructed yet.
There's just one thing I would like to add to the accepted answer, because I don't entirely agree with his conclusion.
We've all done this.
class Engine {
public Engine() {
init();
}
void init() {
lockDoors();
releasePressure();
tightenSeatbelts();
launchRocket();
}
...
}
Now the question is, which access modifier should we add to our init() function. Should it be private or protected.
make it private <-- keeps subclasses out
make it protected <-- allows subclasses in
Before you make a choice
Now first of all, you should realize that (almost) all code in the Engine class can be replaced by a subclass.
code in a public function, can easily be overridden
code in a protected function, can easily be overridden
code in a private function, can be replaced by overriding all methods that call it.
Well, there is just one exception:
you can never modify the code of a constructor
you can never avoid a private method being called from the constructor of a super class.
(and of course, you cannot replace a final method)
Protected init() - the wrong way
Let's say the init() method is protected there is indeed a pitfall. It is tempting to override it to add features as follows. That would indeed be a mistake.
class SubEngine extends Engine {
int screws = 5;
void init() {
tightenScrews();
super.init();
}
void tightenScrews() {
// this won't print 5, but it will print 0.
System.out.println("tightening " + screws + " screws");
}
}
Protected init() - the right way
So, basically, you should just disable the parents code and postpone execution to your own constructor instead.
class SubEngine extends Engine {
int screws = 5;
public SubEngine() {
initSubEngine();
}
void init() {
// disable parent code
}
void initSubEngine() {
tightenScrews();
super.init();
}
void tightenScrews() {
// this will print 5 as expected
System.out.println("tightening " + screws + " screws");
}
}
Private init() - you may need a phonecall
Now, what if the init() method is private ?
Like mentioned above, there is no way to disable the code of a parent constructor. And if init() is private you simply cannot disable it.
You'll end up copying the entire Engine class, perhaps just to add 1 line of code.
And that may not be the end of it. Even after copying your class, your copied object won't be an Engine meaning that you won't be able to use your EngineUtil#inspectEngine(Engine engine) function.
Perhaps somebody knew this in advance and made an IEngine interface. Then you can get away with it.
In practice it means you'll have to take your phone, and call to that other department that made the Engine class, and ask them to change their code a little to take away some restrictions.
Intelligent design
There is another way. Constructors are for setting variables. They shouldn't activate anything. Everytime you see a class creating a new Thread from their constructor (or through a private method) that should be a red flag.
class Engine {
public Engine() {
}
public void init() {
lockDoors();
releasePressure();
tightenSeatbelts();
launchRocket();
}
// and you probably also want one of these
public void shutdown() { ... }
...
}
Intention
Of course, your intention may very well be not to open up your code. Perhaps you really don't want to allow others to extend your classes. There certainly can be cases where you want to lock people out.
Be aware that it will also make it harder to write tests for your code.
Anyway that's a different scenario.