Please check the Java code below:
public class Test
{
public static void main(String arg[]) throws Throwable
{
Test t = new Test();
System.out.println(t.meth().s); //OP: Old value
System.out.println(t.meth().getVal()); //OP: String Implementation
}
private TestInter meth()
{
return new TestInter()
{
public String s = "String Implementation";
public String getVal()
{
return this.s;
}
};
}
}
interface TestInter
{
String s = "Old value";
String getVal();
}
As you see I have created an interface anonymously. When I access the interface variable directly, it will show "Old value".
t.meth().s => "Old value"
Accessing it through the getVal() method returns proper values,
t.meth().getVal() => "String Implementation"
I don't understand how this code works, can somebody explain it to me?
The s variable declared in the interface is entirely separate from the s variable you've declared in your anonymous inner class.
Interface variables are really just designed to be constants - they aren't part of the API each implementation needs to provide. In particular, they're implicitly static and final.
From the JLS section 9.3:
Every field declaration in the body of an interface is implicitly public, static, and final. It is permitted to redundantly specify any or all of these modifiers for such fields.
The fact that you've accessed the field via an implementation instance is irrelevant - this code:
System.out.println(t.meth().s);
is effectively:
t.meth();
System.out.println(TestInter.s);
I would strongly encourage you to avoid using variables in interfaces except for genuine constants... and even then, only where it really makes sense. It's not clear what you're trying to achieve, but declaring a field in an interface isn't a good way forward IMO.
There is nothing like variable-overriding like method overriding in java. Name a new type for subclass, then you will get the "String Implementation", when you access through the subclass reference type.
Access privilege protected only means we can access the variable in a subclass but not that it can be override.
Even if you are using normal class instead of interface this won't work. When you refer using super class type, you only get the instance variables from super type and so on....
This example illustrates the first case:
Example:
public class Tester
{
public static void main(String arg[]) throws Throwable
{
Tester t = new Tester();
System.out.println(t.meth().s); // it prints "Old value" because your type is TestInter
}
private TestInter meth()
{
return new TestInter()
{
protected String s = "String Implementation";
};
}
}
class TestInter
{
protected String s = "Old value";
}
This example illustrates the second case:
It prints "String Implementation"
public class Tester
{
public static void main(String arg[]) throws Throwable
{
Tester t = new Tester();
System.out.println(t.meth().s);
}
private SubTestInter meth()
{
return new SubTestInter();
}
}
class SubTestInter extends TestInter{
protected String s = "String Implementation";
}
class TestInter
{
protected String s = "Old value";
}
When i access a interface variable directly
You have the reference of Interface type, that's why it refers to interface directly and you get "Old value"
Accessing getVal() method, showing proper values
When you invoke method getVal() you refer to actual implementation of this method and that's why getVal of actual implementation is called. This means current instance with the following value:
public String s = "String Implementation";
Fields declared in an interface are constants.
Thus, when writing
interface TestInter
{
String s = "Old value";
String getVal();
}
You are declaring a constant s.
That's why t.meth().s is printing Old value
t.meth().getVal() is printing the content of the field s of your anonymous class.
Related
Please tell me if I have the proper understanding of the following code:
public class Test {
public static void main(String[] args) {
A a = new A();
a.print();
}
}
class A {
String s;
A(String s) {
this.s = s;
}
void print() {
System.out.println(s);
}
}
The line “A a = new A();” invokes the class/constructor to create a new object with reference variable “a”. Class A has a defined constructor that requires a string argument, thus it does not have the default constructor. This means that the instantiation without any string arguments causes a compiler error.
If I were to add a string argument into the instantiation, e.g. A a = new A("goldfish"); the program would compile and run.
I am not sure if I have used the right vocabulary for this, so feel free to correct anything that is inaccurate/confusing. Thanks!
Your understanding is pretty much correct. The one thing that I would change is "create a new object" to "create a new instance of A" with a reference to a java.lang.String in parameter s. In this case the constructor assigns that parameter to a field, but it can do something else with it entirely (such as use it to calculate a different value for some field).
What you wrote is roughly correct.
To be more precise: "invokes the class/constructor" is not entirely correct. A a = new A(); intends to invoke the constructor (invoking a class doesn't mean anything).
Though constructors are not methods, you can think of them a bit like methods: if your class has defined a method like so :
public void myMethod(String s) { ... }
Then trying to call myMethod() without any argument would fail. It's the same here.
Sorry for the vague title; I'm not entirely sure what the problem is.
Background
In short: child classes of a certain base class must define 3 specific static methods, hiding the base class' static methods. An implementation description class checks this on initialization. Seemingly at random when running the application, however, I get run time exceptions during initialization saying that I haven't properly reimplemented the methods. But I am working in unrelated classes elsewhere when this happens, as rarely as it does, and simply shuffling the order of the methods fixes it for another long while.
Code
So, three classes: The Base, the Derived, and the AlgImplementation class:
AlgImplementation constructor:
/* verifying that the extending class has implemented these methods */
if (this.getAlgorithmClassName() == null) {
throw new IllegalArgumentException("The Algorithm Class of this algorithm has not re-implemented the getAlgorithmClassName() method from as specified.");
}
if (this.getAlgorithmClassDescription() == null) {
throw new IllegalArgumentException("The Algorithm Class of this algorithm has not re-implemented the getAlgorithmClassDescription() method from as specified.");
}
if (this.getAlgorithmClassAnalyticLevel() == null) {
throw new IllegalArgumentException("The Algorithm Class of this algorithm has not re-implemented the getAlgorithmClassAnalyticLevel() method from as specified.");
}
That's where the problem happens, one of those checks fails. I get the IllegalArgumentException from one or more of the above. I can simply move the order of the implementation around in the derived class, to force a rebuild of that code, and then it works fine.
Base & Derived classes both have the same simple static methods, but the static fields they return are defined differently:
class Derived extends Base {
public static AnalyticLevel getAlgorithmClassAnalyticLevel()
{
return ANALYTIC_LEVEL;
}
public static String getAlgorithmClassName()
{
return NAME;
}
public static String getAlgorithmClassDescription()
{
return DESCRIPTION;
}
}
The above fields are all non-null static final Strings.
Now, in the Derived class I declare a static final AlgImplementation field:
public static final AlgImplementation derivedAlg = new AlgImplementation("xyz", Derived.class, "Our XYZ derived class", "");
Finally, the last thing I think you will need to know is that that this AlgImplementation instance does the this for each static method class:
public String getAlgorithmClassName() {
String className = "";
try {
className = (String)algorithmClass.getDeclaredMethod("getAlgorithmClassName", new Class<?>[0]).invoke(null, new Object[0]);
} catch (Exception e) {
throw new UnsupportedOperationException("Required static method getAlgorithmClassName() not implemented on "+this.getClass().getName());
}
return className;
}
Finally
So, my question is: How can the check for the derived methods fail if these methods are in fact declared? Is there an issue with declaring a static AlgImplementation field that refers to the very class it is defined in (causing some weird order of compilation issue, or something like that)?
The error is during initialization of Derived class, specifically at the line initializing the static AlgImplementation field, which is why I think there might be a problem with doing that in the Derived class itself.
I suspect the problem is due to initialization order of the static final fields of the classes. By using reflection during class initialization, you're accessing the class before it has fully initialized. If on a derived class, you have the following:
public static final String NAME;
static {
NAME = "some name";
}
public static final AlgImplementation derivedAlg =
new AlgImplementation("xyz", Derived.class, "Our XYZ derived class", "");
then AlgImplementation will check the NAME constant after it has been initialized, and will read the "some name" string. If you reverse the order:
public static final AlgImplementation derivedAlg =
new AlgImplementation("xyz", Derived.class, "Our XYZ derived class", "");
public static final String NAME;
static {
NAME = "some name";
}
then AlgImplementation will read the constant before it has been assigned, and will read null instead.
I'm not sure if it's possible for this to happen if the NAME is assigned directly by a compile-time constant like this:
public static final String NAME = "some name";
I would have guessed that would prevent the problem, but maybe not. Your statement that "shuffling the order of the methods fixes it for another long while" supports the idea that the problem is due to initialization order. I'd suggest moving the derivedAlg field after all the other constants to encourage it to be initialized last.
Static methods do not participate in class hierarchy. You should always use either staticMethod() or Class.staticMethod() instead.
I have this class declaration
abstract class A {
protected static String message = "Hello";
}
And I want this field to get propagated to subclasses, to avoid typing protected static String message = "Whatever"; (the value of this static field is different in each subclass) in all the subclasses.
I know this won't work:
class B extends A {
static {
message = "Blablabla";
}
}
Because it will actually modify A's message because static fields/methods are not inherited. What I want to know is if there's any other way of doing this, or if I have to rewrite the static field on each subclass.
I would suggest using a protected method getMessage() that gets overridden by each subclass instead of a static field.
class B extends A {
#Override
protected String getMessage() {
return "Blablabla";
}
}
There's no straightforward way to do it.
You may consider use some utility class which maps a Class object to a message. This will help you use general methods to work with messages based on this.getClass().
I usually create a get method in this case:
abstract class A {
private static final String DEFAULT_MESSAGE = "Hello";
protected String getMessage() {
return DEFAULT_MESSAGE;
}
}
That makes it easy to override the message in subclasses where I want to.
Static fields and methods are inherited - as a C programmer, I was told to think of them as being similar to "global" variables, namespaced to the class (and with private/protected restrictions).
From your first snippet, B.message will be "Hello".
You have to make it either
public class A {
protected String message = "Hello";
}
or
public class A {
private static String message = "Hello";
}
public class B {
private static String message = "Howdy";
}
Would an aspect let you achieve what you want to do? From one place you could configure/manage the return value for a method with a specific nam, on a class-by- class basis. ...it would still be more work than duplicating the same boiler plate "private static ..." in each subclass.
I have a Super class and a bunch of subclasses. I want to have one field that has the same name in every single subclass, but I do not want it to be defined in the super class, or at least I do not want to use that value. This is what I have right now
public abstract class Big {
public String tellMe = "BIG";
public Big() {}
public void theMethod() {
System.out.println ("Big was here: " + tellMe() + ", " + tellMe);
}
public String tellMe() {
return tellMe;
}
}
public class Little extends Big{
public String tellMe = "little";
public Little(){}
public String tellMe() {
return "told you";
}
public static void main(String [] args) {
Little l = new Little();
l.theMethod();
}
}
When I run Little, this is the output
Big was here: told you, BIG
I am not sure why 'told you' is printed out while tellMe refers to "BIG". How can both be true?
My problem is that I want the method tellMe() to be in Big, and to have the variable tellMe (that it will actually return) to be defined in all the subclasses. The only way I can get this to work is as I have written, by rewriting the tellMe() method in each subclass. But doesn't that defeat the whole purpose of inheritance??? Please help
EDIT: I do not use the constructor in my subclasses. All I want is a field that can be set in all subclasses and a method in the super that uses those values. I don't understand why this isn't possible because every subclass would have to implement it, so it would make sense... If this simply is not possible, let me know please
Fields are not virtual, unlike methods. For this reason, it is a bad idea to declare fields with the same name as a field in another class in the hierarchy. The field referred to in theMethod is always going to be from Big (i.e. when you declare a field with the same name, it just hides the old field when in the scope of the replacing class, but doesn't replace it).
One solution would be to override a method that gets the field from the current class:
In theMethod replace the tellMe field with getTellMe() and for all classes override getTellMe() to return the correct value (or the field that hides the superclass's field).
You can overwrite the value of Big.tellMe in the constructor of Little.
get rid of:
public String tellMe = "little";
and change the Little constructor to:
public Little(){
tellMe = "little";
}
at that point, you can get rid of Little.tellMe() also.
What you are doing is hiding the super class field, not overriding it, as the Java documentation states.
And it's also stated that it's not a good idea to do it.
So, the dynamic lookup won't work as for a method. If the variable is read from the son class, it will take "its" field value.
On the top class, the other one.
What you can override in Java is the behaviour, so what I would suggest is to
define a method
public String tellMe() {
return "Whatever";
}
that you can override in the subclasses to return whatever string you need.
Instead of defining tellMe inside of Big (since you said you do not want to define/use that value in Big) you can create a function in Big:
public abstract String tellMeString();
And define that in each subclass like so (for Little):
public String tellMeString()
{
return "Little";
}
Then theMethod can execute:
System.out.println ("Big was here: " + tellMe() + ", " + tellMeString());
In this case you wouldn't have to define a variable "tellMe" at all, you just override tellMeString in each subclass to return different Strings.
Fields are not inherited as you are expected. You can access the super class' field (unless it is private) from subclass. But you cannot "override" field. This is why tellMe used by method implemented in super class Big uses variable defined in the same class.
If you want inheritance use methods. For example you can implement method "tellMe()" that returns "BIG" in super class and "little" in subclass:
class Big {
protected String tellMe() {
return "BIG";
}
}
class Little {
#Override
protected String tellMe() {
return "Little";
}
}
Alternatively you can initialize variable tellMe in constructor:
class Big {
private String tellMe;
public Big() {
this("BIG");
}
protected Big(String tellMe) {
this.tellMe = tellMe;
}
protected String tellMe() {
return "BIG";
}
}
class Little {
public Little() {
super("Little");
}
}
Now new Little().tellMe() will return "Little": the variable in super class was initialized when constructing the object; the method defined in super class returned this variable.
Methods can be overridden, fields are visible at the scope where they're called.
static class Big {
String field = "BIG";
String bark() { return "(big bark)"; }
void doIt() {
System.out.format("field(%s) bark(%s)\n", field,bark());
}
void doIt2() {
System.out.format("2:field(%s) bark(%s)\n", field,bark());
}
}
static class Small extends Big {
String field = "small";
String bark() { return "(small bark)"; }
void doIt2() {
System.out.format("2:field(%s) bark(%s)\n", field,bark());
}
}
public static void main(String... args) {
Big b = new Big();
b.doIt();
b.doIt2();
Small s = new Small();
s.doIt();
s.doIt2();
}
Output is:
field(BIG) bark((big bark))
2:field(BIG) bark((big bark))
field(BIG) bark((small bark))
2:field(small) bark((small bark))
since doIt() is defined in the Big class, it will always see the Big version of field. doIt2() is defined in Big, but overridden in Small. The Big.doIt2() sees the Big version of field, the Small.doIt2() version sees the Small version of field.
As others have pointed out, it's a pretty bad idea to do this - a better approach is to set the new value in the subclass constructor, or to use a method which is overridden.
I have an example class defined like below:
public class FooBar {
void method1(Foo foo){ // Should be overwritten
...
}
}
Later, when I try this:
FooBar fooBar = new FooBar(){
public String name = null;
#Override
void method1(Foo foo){
...
}
};
fooBar.name = "Test";
I get an error saying that the name field does not exist. Why?
Because the type of the variable "fooBar" is FooBar (the run-time type of the object in said variable is that of the anonymous class implementing FooBar which is also a subtype of FooBar)...
...and the type FooBar does not have said member. Hence, a compile error. (Remember, the variable "fooBar" can contain any object conforming to FooBar, even those without name, and thus the compiler rejects the code which is not type-safe.)
Edit: For one solution, see irreputable's answer which uses a Local Class Declaration to create a new named type (to replace the anonymous type in the post).
Java does not support a way to do this (mainly: Java does not support useful type inference), although the following does work, even if not very useful:
(new foobar(){
public String name = null;
#Override
void method1(Foo foo){
...
}
}).name = "fred";
Happy coding.
Both Scala and C# support the required type inference, and thus anonymous type specializations, of local variables. (Although C# does not support extending existing types anonymously). Java, however, does not.
A local class would do
{
class MyFooBar extends FooBar{
String name = null;
...
};
MyFooBar fooBar = new MyFooBar();
fooBar.name = "Test";
}
You're creating an object of type foobar. The compiler only knows about the members defined for the class/interface foobar.
Remember, java is a static language, not dynamic. It doesn't check the object at runtime for what exists, it checks at compile time based on the type declaration.
Try this.
#SafeVarargs
public static <T> void runWithObject(T object, Consumer<T>... progs) {
for (Consumer<T> prog : progs)
prog.accept(object);
}
and
runWithObject(
new FooBar() {
String name = null;
#Override
void method1(Foo foo) {
System.out.println("name=" + name);
}
},
object -> object.name = "Test",
object -> object.method1(new Foo())
);
result:
name=Test
Or you can use var like this in Java 10 or later.
var fooBar = new FooBar() {
public String name = null;
#Override
void method1(Foo foo) {
System.out.println("name=" + name);
}
};
fooBar.name = "Test";
fooBar.method1(new Foo());
fooBar is a reference to an object of type foobar, and such objects do not have a field name. Simple as that. And since it’s an anonymous type, the only way to reference that field is through its this reference.
fooBar type is foobar which has not such variable and therefore the code can not be compiled. You can access it by reflection.
As everyone said, this is due to static typing and FooBar class does not contain name. So it won't work.
I wanted to point out the suggested usage of Anonymous class.
Anonymous class (or close to Closures, maybe lambdas. Similar but not same) come from functional programming paradigm, where the states should be immutable.
That being said, why should you user such classes? When you need a quick and short thing to be done which should not necessarily go in a complete class. Example:
MyTask() //This is a method
{
new Thread(new Runnable() { //Anonymous class
public void run()
{}
}).start();
}
The understanding of enclosing your implementation only to a function/class is important.
The scope of the variables defined in the Anonymous class (or closed-over function) should only be used inside the Anonymous class, it cannot be accessed from other program code.
Therefore, you should not (and anyway cannot) set fooBar.name = "Test";
You can also do it like this
Boolean var= new anonymousClass(){
private String myVar; //String for example
#Overriden public Boolean method(int i){
//use myVar and i
}
public String setVar(String var){myVar=var; return this;} //Returns self instane
}.setVar("Hello").method(3);