In what context are statements in Java interface definitions executed? - java

I'm looking at the definition of org.apache.maven.plugin.Mojo:
public interface Mojo
{
String ROLE = Mojo.class.getName();
[...]
}
I'm lost. To my knowledge, Java interfaces are a set of method signatures. So what's this line which looks like a statement doing here? What are the semantics? For example:
When does that line get "executed"?
In the context in which that line runs, what does Mojo refer to? What is its type?
In the context in which that line runs, what does Mojo.class refer to? I assume its type is java.lang.Class?
In what context can I read that ROLE variable? What is the syntax for doing so? What will the variable contain?
Can I write to that ROLE variable?

All the fields of an interface are implicitely public, static and final. So this is the same as writing
public static final String ROLE = Mojo.class.getName();
It defines a constant, that all the users of the interface can use, as any other constant: Mojo.ROLE. This line is executed when the Mojo interface is initialized by the ClassLoader. Mojo.class is the Mojo class, indeed of type java.lang.Class<Mojo>. Since the package of the class is org.apache.maven.plugin, the value of the constant will be "org.apache.maven.plugin.Mojo".
Look here for the relevant section of the Java language specification.

the variable get defined when class loader loads the class.
interface variables are static final and can be accessed statically by any class that implements the interface.
public class MyClass implements Mojo{
.
.
.
}
access:
public void someMethod(){
System.out.println(MyClass.ROLE)
}

All fields in an interface are implicitly static and final. That answers some of your questions:
The line gets executed during the static execution. That is possibly during compilation, possibly at the launching of the program and possibly when the class loader loads that class. It's a complicated business, but it's the same as all other static fields.
Mojo refers to the interface itself, statically. It is a type itself, so it has no type.
Mojo.class refers to the java.lang.Class of Mojo.
You can read the ROLE variable in any class that implements Mojo. You can only read it statically, like Mojo.ROLE.
No, the field is final, so you can't write to it. It is intended for constants only.

When does that line get "executed"?
Any member of an Interface is static and final by default, so String ROLE (which can effectivly be seen as
public static final String ROLE
will be initialized, as every static member, when the ClassLoader loads the class (by the first time, the class is referenced).
JLS - Loading of Classes and Interfaces
In the context in which that line runs, what does Mojo refer to? What is its type?
In the context in which that line runs, what does Mojo.class refer to? I assume its type is java.lang.Class?
Mojo is of the type java.lang.Class<Mojo>
In what context can I read that ROLE variable? What is the syntax for doing so? What will the variable contain?
As it is implicit public static final you can access it from everywhere by using Mojo.ROLE or through the implementing classes by ClassName.ROLE. As Class#getName() says in the java doc, it will contain the full qualified name of the object:
org.apache.maven.plugin.Mojo
Can I write to that ROLE variable?
No, you cannot, because it is implicit final
JLS - Interfaces

Related

Use dynamic class name in private static final variable of a class

Consider and example as below:
public class LoggerTestClass {
private static final Logger LOGGER = Logger.getLogger(LoggerTestClass.class);
}
In above example parameter passed to getLogger method is hard coded i.e LoggerTestClass.class
Now every time I change the class name I have to change the getLogger method's parameter.
Any other way which will fetch the class name automatically, for example for non static variable we can add this.getClass()
You can use Lombok to achive it in a clean fashion. All you need to do is to put #Log on top of your class and it will give you a log object to work with.
Read more here
Bro,For the question,first of all,we need make clear some concept.
In java,if a identifier is a member of a class,and decorated by 'static' keyword,it's value is Decided in the compile phase.
If the 'final' keyword is added,the identifier is constant,it's value must have a initial value on it is declared.and the value can't be change in the java runtime.
And the interesting thing is, the static constent is only declared inside the class,it can be called 'Classname' + '.' ,but has no connection to the class context.if there's no context ,the identifier con't become dynamic.
I think if let the identifier become dynamic ,there are only two ways:
let the identifier become a variable.remove the 'final' key word.the code look like this:
class Test {
private static Logger LOGGER;
public Test() {
LOGGER = Logger.getLogger(getClass().getSimpleName());
}
}
The 'private' keyword is sufficient if you don't want other classes to access it.
Try the java dynamic proxy. it can change the class in java runtime.
Code happy ~
Welcome to talk with me~
Can you use java 9+? Then solution is pretty simple:
private static final Logger LOGGER = Logger.getLogger(MethodHandles.lookup().lookupClass());
As MethodHandles.lookup() creates lookup using caller class. (via Reflection.getCallerClass() but Reflection is internal API, so you need that additional method handle lookup step)

class and private members [duplicate]

This question already has answers here:
Why is the access to a private field not forbidden?
(6 answers)
Closed 8 years ago.
class MC {
private String name;
void methodA(MC mc){
System.out.println(mc.name);
}
}
Why am I able to access name variable in methodA? I am confused here, can someone please explain?
You can access it because methodA is part of class MC. Every method in a class can access that class's private data members (in the current instance and in any other instance). Only other classes cannot. For example:
class MC {
private String name;
void methodA(MC mc){
System.out.println(mc.name);
}
}
class SomeOtherClass {
void printMC(MC mc){
System.out.println(mc.name); //compiler error here
}
}
Here is some official documentation on this topic: http://download.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html
Because private does not apply to the object, it applies to the class. If private applied to the object, then your intuition would be correct: MC.methodA would have access to this.name, but it would not have access to mc.name (where mc is some other MC object).
However, a subtle rule of visibility modifiers is that they control access for any code in that class to the members of the other objects of that same class. So all of the code in the MC class has access to the private name field of all objects of type MC. That is why MC.methodA has access to mc.name (the name of some other MC object) and not just its own name.
Edit: The relevant section of the Java Language Specification is 6.6.1 Determining Accessibility:
Otherwise, if the member or constructor is declared private, then access is permitted if and only if it occurs within the body of the top level class (§7.6) that encloses the declaration of the member or constructor.
because you have accessed it from the scope it's private to.
your private implementations and data will be private to (and accessible in) the scope (e.g. class) they have been declared in.

final static String defined in an interface not evaluated at compile time - Android

I have two classes and an interface (for example DatabaseModel, LocalStore, and InternalModelInterface). They're defined as follows;
public class DatabaseModel {
// ...
public static final String KEY_PARAM1 = "param1";
}
public class LocalStore implements InternalModelInterface {
// ...
public void function () {
String temp = InternalModelInterface.COLUMN_PARAM1;
}
}
public interface InternalModelInterface {
public static final String COLUMN_PARAM1 = DatabaseModel.KEY_PARAM1;
// ...
}
The issue I'm experiencing is that at runtime, when I call localStore.function(), temp is being assigned null, as InternalModelInterface.COLUMN_PARAM1 is null. Does this make sense? Shouldn't InternalModelInterface.COLUMN_PARAM1 be evaluated at compile time and inlined?
This is for an Android application. Thanks in advance.
I'll further explain to clarify any confusion.
Objects of the DatabaseModel class are instantiated as a JSON response is parsed. The constants defined in the DatabaseModel class represent the keys to look for in the JSON response.
The InternalModelInterface defines the column names used in the local (cache) database on the device. For several reasons (including they keys being illegal column names in SQLite), I'm not reusing the keys as column names.
The reason I'm using an interface and not just a plain class is that the interface also specifies required methods that need to be implemented by the third class, LocalStore.
JLS3 §8.3.2.1, §9.3.1 http://java.sun.com/docs/books/jls/third_edition/html/classes.html#38010
at run time, static variables that are
final and that are initialized with
compile-time constant values are
initialized first. This also applies
to such fields in interfaces (§9.3.1).
These variables are "constants" that
will never be observed to have their
default initial values (§4.12.5), even
by devious programs.
So null should never be observed in your example. It's an Android bug then.
I'm not and android expert but I think that if you don't create an instance of the class, it's optimised out at compile time. If you create a constructor for DatabaseModel and instantiate it somewhere it seems to solve this for me.

Scope of protected members

Iam preparing for SCJP , also i came to know that protected members scope is within the package as well as in other package with some conditions like possible only with inheritance.
For example :
i have three classes as Parentclass Childclass Friendclass
package x.parent;
class Parentclass{
protected int x=10;
...............
}
package x.child;
class Childlass extends Parentclass{
super.x=20;
...............
}
package x.child;
import x.parent.Parentclass;
class Friendclass{
Parentclass pc = new Parentclass();
pc.x=30;
...............
}
Whats the reason behind that, in Friendclass the member x will not accept to assign a value to that, behaves as private member not in case of Childclass.
There are four access modifiers
private - just this class
no modifier - just this class or this package (NOT subclass)
protected - just this class, this package, or subclass
public - everyone and their cousin
Since it uses the default modifier, it has access if one of the following is true:
Is part of the class itself (Nope!)
Is part of the package of the class itself (Nope!)
So it fails the criteria, and so you don't get access.
You can't even access Parentclass.x in Childclass because x has default visibility (not protected). See http://download.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html
edit:
x.child.Friendclass is not in the same package as x.parent.Parentclass.
x.child.Friendclass does not inherit from x.parent.Parentclass.
as TotalFrickinRockstarFromMars's summary states and the Java access control docs also state, this means that Friendclass is not allowed to access the field x.

What is "logger" in Java?

I have a class in which I see the following things:
this.logger.severe("");
this.logger.warning("");
this.logger.info("");
I do not understand several things:
How can we use a method that was not defined earlier? I mean, there are no "logger" methods defined in the class. I thought that these methods could be defined because the considered class is an extension of another class in which the "logger" is defined. But in the definition of the class there no "extends" statement (only "implements").
I can understand things like that: "objectName.methodName". But what is that "objectName.something1.something2"? "something1.something2" is name of a method? Can method names contain dots?
What exactly these "logger.*" do? I think they save information about the execution of the code. They kind of write report about what happened during the execution. But where I can find this information?
ADDED:
In the beginning of the file I have: import java.util.logging.Logger;
And then in the class I have: private Logger logger = Logger.getLogger("a.b.c.d");
So, logger is an object of the class Logger (but I do not understand why they could not instantiate the class in a usual way using "new Logger()). I also do not understand what exactly logger.severe("") do.
The logger doesn't make anything special. It's all just Java code.
public class SomeClass {
private Logger logger = LogFactory.getLogger(SomeClass.class);
public void doSomething() {
this.logger.debug("foo");
}
}
The this.logger just points to the instance variable named logger of the current instance (this). The this. prefix is by the way superflous in this example. One could also just do logger.debug("foo") here.
If it is not declared in the SomeClass itself, then it's likely been declared in the extending class. Check the class which is declared in extends.
As to your objectName.something1.something2 doubt, have you already looked how System.out.println() works? The System.out returns a PrintStream object which in turn has a println() method. Thus, if objectName.something returns a fullworthy Object with methods, then you can just continue chaining method calls.
Basically,
objectName.something1.something2;
can be translated as
SomeObject someObject = objectName.something1;
someObject.something2;
But if you don't need someObject anywhere else in the code, then it can just be shortened as in your example.
Update: as per your update:
So, logger is an object of the class Logger (but I do not understand why they could not instantiate the class in a usual way using "new Logger()). I also do not understand what exactly logger.severe("") do.
Just read the javadoc of the class in question what it all does. As to why it can't be instantiated, it's because of the factory pattern.
Update 2: as per the another confusion:
I do not understand why they use "this". I mean, if I use just field name, will it not be, by default, the field of this object? I there any difference between "this.x" and "x"?
This way you can be more explicit about which one you'd like to access. If the method contains for example an argument or a local variable with the name logger, then this.logger would still refer to the instance variable.
public class SomeClass {
private Logger logger = LogFactory.getLogger(SomeClass.class);
public void doSomething(Logger logger) {
this.logger.debug("foo"); // Refers to the instance variable.
logger.debug("foo"); // Refers to the method argument.
}
public void doSomethingElse() {
Logger logger = LogFactory.getLogger(SomeClass.class);
this.logger.debug("foo"); // Refers to the instance variable.
logger.debug("foo"); // Refers to the method local variable.
}
}
The logger usually refers to the usage of a class in log4j.
The logger is a member object whose function e.g. severe is called.
The logger usually logs into a file (this can be configured through log4j.xml or some other config file or during the program start).
Edit: Changed the log4j link.
The 'logger' will be another object, not a method. This logger class will have methods defined on it like public void severe(String message)
'something1' will be an object contained by 'objectName'. For example, Car.Engine.Cylinder.Fire(), it's considered bad practise to use a method to fire a car's cylinders like this, and you should do something more like Car.StartEngine() (see the law of demeter for more info)
The logger will keep a record of what's happened in your program, so if there's a crash or a bug later on, you can see what happened. Whether this is recorded to a text file, or to a database somewhere, will be down to the implementation of your logger.
logger is not a method but a class variable which seems to be an object that exposes the methods "severe", "warning" and "info".
Check your class for something like "someClass logger = new someClass();"
The java.util.Logger class is the main access point to the Java logging API. Here is how you create a logger:
Logger logger = Logger.getLogger("myLogger");
The string passed as parameter to the getLogger() factory method is the name of the Logger to create. You can choose the name freely, but the name implies where the Logger is located in the Logger hierarchy. Every . (dot) in the name is interpreted as a branch in the hierarchy.

Categories

Resources