Access level aware dependency injection into inherited field - java

At work there is a process framework. It uses keys and containers to set parameters without the use of dedicated constructors (it's basically the type safe heterogeneous container pattern).
I recently added dependency injection.
Below you find a representative example (it lacks some null checks, access control, etc.)
private static void inject(Process instance, Container c) throws Exception
{
Class<?> reference = instance.getClass();
for (Field field : reference.getDeclaredFields())
{
Inject inject = field.getAnnotation(Inject.class);
Key<Object> key = new Key<>(inject.key());
field.set(instance, c.getObject(key));
}
}
The implementation is working, but now I need to enhance it in order to also inject into inherited fields.
I had no problem retrieving the type hierachy and all the annotated, inherited fields. But in order to comply with Java, I must not inject into every retrieved field.
Only when the field is:
public
protected
package-privated and declared in a class that has the same package as reference
private and declared in class that encloses reference, which has to be an inner class (non-static nested class).
Items 1 - 3 are easy to check for. I have difficulties with the last item. Is there an elegant solution?
I thougt about using java.lang.Class.isMemberClass() and comparing class names.
Currently my check looks like this
private static boolean accessAllowed(Class<?> reference, Field field)
{
int modifiers = field.getModifiers();
boolean hasAccess = Modifier.isPublic(modifiers);
hasAccess |= Modifier.isProtected(modifiers);
// TODO fix
hasAccess |= Modifier.isPrivate(modifiers) /* add check as defined in 4. */;
// no access and not private means field is package-private
if (!hasAccess && !Modifier.isPrivate(modifiers))
hasAccess = reference.getPackage().equals(field.getDeclaringClass().getPackage());
return hasAccess;
}
Is there an easy and/or efficient way to find out whether a class is enclosed by another class? Or is there another way to find out whether I am allowed to inject?

The following solution should handle the private case.
The derived class is reference, it tries to set members inherited from fieldDeclaringClass
static boolean hasPrivateAccessRelation(Class<?> reference, Class<?> fieldDeclaringClass)
{
boolean isMemberClass = reference.isMemberClass();
boolean isEnclosingClass = reference.getName().contains(fieldDeclaringClass.getName());
// static nested classes can't access private members of enclosing class
return isMemberClass && isEnclosingClass && !Modifier.isStatic(reference.getModifiers());
}
The code works if the derived class is a inner class of fieldDeclaringClass. It fails if it is a static nested classes, since these have no access to private fields of enclosing classes.
A previous check is necessary to make sure reference and fieldDeclaringClass are not equal. Because in that case static would be a valid modifier, since a nested class always has access to its own fields.

Related

What happens to variables/objects in inner classes of function objects?

I have a function multi2 which returns inner class Inner as an Object.
What happens to a - where is it saved and how can I access it?
public class C {
private static Object multi2(final int a) {
class Inner {
public int hashCode() {
return 2*a;
}
}
return new Inner(); // What happens to a?
// Who allocates a?
// Can I Access a?
}
public static void main(String[] args) {
Object o = multi2(6);
System.out.println("o.hashCode() = " + o.hashCode());
o = multi2(4);
System.out.println("o.hashCode() = " + o.hashCode());
}
}
What happens at the implementation level is that a copy of the value of a is saved in a synthetic instance variable declared in the compiled version of the C.Inner class.
The value of a is passed to the compiled Inner constructor via an extra parameter.
The C.Inner.hashCode method uses the value of the synthetic variable. Accessing a in the source code of Inner.hashCode is transformed into accessing the corresponding synthetic variable in the compiled code.
The variable in the outer scope must be final1. The synthetic variable must be final2 in the Inner class. This maintains the illusion that (potentially) multiple instances of the Inner class are seeing the same a variable. (They aren't, but since the variable(s) can't be changed, it is not possible for the code of the inner class to tell the difference.)
If you use javap to look at the bytecodes for the compiled example, you will see the mechanisms used to implement this in the outer and the inner classes.
1 - or effectively final from Java 8 onwards.
2 - If a could be mutated by an Inner method, then two Inner instances with the same outer class need to share a mutable variable whose lifetime is (now) longer than the stackframe for a multi2 call. That entails somehow turning a from stack variable into something that lives on the heap. It would be expensive and complicated.
You have defined the class Inner inside the function so the scope of the class will be
restricted with in the method. And your function is static so it will be live as long as the class definition is loaded. You have override the hashCode function inside the InnerClass so every time you are calling the multi2(param) you are creating the hashCode for the instance of InnerClass and returning the instance of the InnerClass.
So as for you questions, please correct me if i am wrong.
What happens to a ?
a is with in the scope of your static method, so it will be live as long as the class definition is loaded.
Who allocates a?
scope of a is restricted inside the static method and static method does not require instance to access it but as for the static method/variable allocation, i think it depends on JVM.
Can I Access a?
No you cannot access a from outside you static method, it is restricted with in your static method.
Since the "a" is a local parameter, you could use a different approach to read the "a" value:
public class C {
public static Object multi2(final int a) {
return new Inner(a);
}
public static void main(String[] args) {
Object o = multi2(6);
System.out.println("o.hashCode() = " + o.hashCode());
System.out.println("o.getA() = " + ((Inner) o).getA());
o = multi2(4);
System.out.println("o.hashCode() = " + o.hashCode());
System.out.println("o.getA() = " + ((Inner) o).getA());
}
}
class Inner{
public int valueA;
public Inner(int a)
{
valueA = a;
}
public int getA() {
return valueA;
}
public int hashCode() {
return 2*valueA;
}
}
I wanted to know what was actually happening, so I compiled your code and looked at the bytecode output.
Basically what happens is the compiler adds in a constructor to your class 'Inner'. It also adds a single parameter to that constructor which takes 'a'. If your multi2() method was NOT static then there would probably also be a parameter to take 'this' where 'this' is the instance of 'C' that multi2() is executing on. BUT since we're in static context, there is no 'this'.
The compiler adds a private final field to your class 'Inner' and sets that private field using the value passed via the constructor. The compiler also converts
new Inner()
into
new Inner(a)
Hashcode then accesses the private field containing the value for a.
If 'a' was an object instead of a primitive, then it would be the same way, but a reference would be passed through instead of an actual number value.
How do you access this variable? Well you access it with reflections, but there are many problems:
1) You don't know the name of the field made by the compiler, so you can only get the name by looking at the bytecode. Don't trust decompilers as they might change the name. You gotta look at the bytecode yourself to find out.
2) The compiler probably marks the field as final, which means even if you can get reflections to access the field for you, you won't be able to update it.
3) It is entirely up to the compiler to figure out field names. Field names could change between builds depending on the compiler and it's mood.
Inner is a so called local class. a is a parameter passed to the method multi2 and accessable within that scope. Outside of that method, you cannot access a.

How to use a Get method in java

A ton of questions have been asked on how to create getter and setter methods in java. But i have yet to see one that actually tells me how to use it.
Say i have Private int i = 1; in class A and i want to access it in class B.
I would first create a get method in class A called getIntI(); which would return the value of i.
Then in class B if i wanted to create an if statement that would need the value of i how would I get int i's value. The following is my try and calling the get method which does not work.
if(getIntI == 1)
{System.out.print.ln("int i is one");}
It is probably a really stupid question but i cant find an answer for it elsewhere.
In class A:
public int getIntI(){
return i;
}
Note: Now since your variable is single character named (just I), getter method is named getIntI since the name getI makes lesser sense. But generally, getter methods are something like get+VariableName and do not involve mentioning type. For example if I had a variable called int count, my method would be named getCount instead of getIntCount. Thats the general convention.
Also, naming variables in single char formats (like x, y etc) is discouraged because it may create confusion and management difficulty in complex programs. Though in very small programs they are fine.
Moving back to topic, if you want to access method getIntI() in class B, you will either have to inherit class A or create an object of class A reference to its method.
For class B:
Creating object
A obj = new A();
if(obj.getIntI() == 1)
// Do stuff
Inheriting class A:
public class B extends A{
... // Your stuff
if(getIntI() == 1)
// Do stuff
... // Your stuff
}
Of course there are other ways but these are simpler ones.
if class B extends class A then do only this changes,
if(getIntI() == 1)
If above inheritance was not there then do this,
if(new A().getIntI() == 1)
The problem is that you need to create a object derived from class A before you can access its variables/methods using
A a = new A();
where "a" is the name of the object. Then you can access the getter method by calling a.getIntI. You can also declare the int variable as static so that you wouldn't have to instantiate any objects. An example of class A with the static variable and getter method would be:
public class A {
private static int i = 1;
public static int getIntI() {
return i;
}
}
With this, you can call the getter method with A.getIntI().
First, if you want to access one of A's non-static methods (in this case, getIntI), you need an instance of A, or you can just declare it static.
Secondly, A method call needs a parameter list, even an empty one is needed. getIntI does not need any parameters, so you should add () at the end.
Now, you can get an instance of A somewhere and call it aObj. Andd then you can use it in the if statement:
if (aObj.getIntI == 1)
And remember to add ()!
if (aObj.getIntI() == 1)
Alternatively, you can declare i in A as static. There are two main differences between a static and a non-static variable.
You don't need an instance of the declaring class to access the static variable.
Unlike non-static variables, there is only one static variable. If you have a non-static variable i, you can create lots of instances of A and each instance will have its own i
Now let's see this in action, declare i as static:
public class A {
private static int i = 1;
public static int getIntI () { return i; }
}
Note how both i and getIntI are declared static.
Then you can use in a if statement like this:
if (A.getIntI() == 1)
Note how I use the class name A to access the method, not an instance of A.

Is there any purpose to make private class variable to public

Hello I am curious to know that Is there any purpose to make private class variable to public in Java.
public class XYZ {
public String ID;
public ABC abc;
private class ABC {
public boolean isExist;
}
}
Thanks in advance.
Yes, there's a purpose. If you do that then those program elements which can access the class can manipulate that variable directly. Otherwise (say if the variable is private), those elements would still be able to access the class but won't be able to manipulate the variable (unless you provide a getter/setter for it).
Think about it this way: the class modifier defines the level of access to the class, the variable modifier then defines the level of access to the variable itself (for those elements which can access the class).
This is sometimes done for data-only classes. For example, this is sometimes done to represent the models stored in databases (see Objectify for a real example of how this is used, in conjunction with annotations, to represent the database models that are stored in an App Engine database).
That being said, this sort of thing makes for a very poor API. If you do this, I'd suggest doing it with classes that are either package-level access or in private nested classes, only. When exposing functionality or data to code outside your package, it is generally better to do it with a carefully designed interface that would allow you to change the implementation if your underlying structure were to change.
That is to make isExist visible to XYZ class.
Note, ABC is only visible to XYZ and not to any outside classes and its variable is public so you can have access to it. private has not meaning to XYZ, only outside classes
From inside XYZ,
ABC abc = new ABC(); //can only be accessed by XYZ.
abc.isExists = true; //can only be accessed by XYZ
Making isExist public means you do not care about encapsulating (prevent it from unwanted manipulation from outside) it. If you make it private, you will need a get accessor to expose it
private class ABC {
private boolean _isExist; //only through accessors
public boolean isExist()
{
return _isExist;
}
}
You can do either of the following two things to your class instance variables:
THING # 1: Keep your instance variables private. Then have public getter and setter methods to get and set the value of that variable. The good thing about it is that you get to put checks inside the setter method. For example, lengths can never be negative. So, you can't just make lengths public and let anyone assign it whatever value they want. You need to make sure the value being assigned to it is not negative. So:
class myClass {
private int length;
public void setLength(int i) {
if ( i > 0 ) {
length = i;
}
}
}
Also, you can make your instance variables read-only, write-only, or read-and-write, depending on the availability of getter and setter methods for that private variable.
THING # 2 : If you don't need any restrictions on the value of your instance variable, and you want it to neither be read-only nor write-only, then it's fine to keep that variable public. For example: babies can have any name - no restrictions:
class Baby {
public name;
}
class Mother {
public void nameTheBaby() {
Baby baby = new Baby();
baby.name = "Sarah";
}
}

Accessing a Super's Member of different type with the same variable name

Consider the following superclass and subclass pair, how do you access the superclass member?
class Super {
Number aNumber;
}
class Subbie extends Super {
Float aNumber;
}
You can access the super Member by super.aNumber provided it is an instance of the Subclass.
Given that the attribute does not have a visiblity modifier, it is assumed to be package private. Subbie will only be able to access Super's aNumber if they're in the same package.
If it was, you could access it like this: super.aNumber. Notice super here is a keyword that implicitly refers to the superclass, and doesn't have anything to do with the superclass being named Super.
class Super {
Number aNumber;
}
class Subbie extends Super {
Float aNumber;
public Number getNumberFromSuper() {
return super.aNumber;
}
}
I'd suggest to take a read on the excellent Java tutorials online, for instance:
Inheritance
Controlling Access to Members of a Class
You can define a field with different keywords known as Access Modifiers (check the links at the end for a detailed explanation on this topic), each one defining a scope for access/use. I'll focus this explanation on fields.
Public: Accessible by everyone. This Access Modifier is regulary used with methods and not with fields. In Java, it is encouraged the use of get and set methods to access the value of a field and change it (respectively). You can access a field this way:
AClass c = new AClass();
c.publicField = 3; //Setting a value in a field, int in this case
int sum = c.publicField + 4; //Obtaining the value of publicField to use it
Private: Definining a field as private makes it visible only to the class itself, meaning no one outside the boundaries of a class will be able to see that field. A common class in Java usually has private fields and accessors (get & set methods).
public class AClass {
public int publicField;
private String privateField = "Can't see me!";
public String getPrivateField() {
return privateField;
}
public void setPrivateField(String newValue) {
privateField = newVaule;
}
}
Getters and Setters let you control the access to your private fields, allowing you to perform any logic you desire before updating the value of that field or preparing a field in a particular before returning its value if you need it.
Protected: Only subclasses of a class and classes in the same package can access a field defined with this keyword. In your case Subbie has access to the protected fields of Super and any other class in the same package as Super has access to those fields as well.
No Access Modifier: This is your current case and the answer to your question relies strongly on the structure of your classes. If they are in the same package, then you can access Super's field from Subbie. Otherwise, if Subbie is in another package, you won't be able to access that field. This field is referenced as Package-Private.
Some related articles you might want to check:
Inheritance in Java
Controlling the Access to Members of a Class

Getting value of public static final field/property of a class in Java via reflection

Say I have a class:
public class R {
public static final int _1st = 0x334455;
}
How can I get the value of the "_1st" via reflection?
First retrieve the field property of the class, then you can retrieve the value. If you know the type you can use one of the get methods with null (for static fields only, in fact with a static field the argument passed to the get method is ignored entirely). Otherwise you can use getType and write an appropriate switch as below:
Field f = R.class.getField("_1st");
Class<?> t = f.getType();
if(t == int.class){
System.out.println(f.getInt(null));
}else if(t == double.class){
System.out.println(f.getDouble(null));
}...
R.class.getField("_1st").get(null);
Exception handling is left as an exercise for the reader.
Basically you get the field like any other via reflection, but when you call the get method you pass in a null since there is no instance to act on.
This works for all static fields, regardless of their being final. If the field is not public, you need to call setAccessible(true) on it first, and of course the SecurityManager has to allow all of this.
I was following the same route (looking through the generated R class) and then I had this awful feeling it was probably a function in the Resources class. I was right.
Found this:
Resources::getIdentifier
Thought it might save people some time. Although they say its discouraged in the docs, which is not too surprising.
I was looking for how to get a private static field and landed here.
For fellow searchers, here is how:
public class R {
private static final int _1st = 0x334455;
}
class ReflectionHacking {
public static main(String[] args) {
Field field = R.class.getFieldDeclaration("_1st");
field.setAccessible(true);
int privateHidenInt = (Integer)field.get(null);
}
}

Categories

Resources