I have several Classes A1,A2,A3 which extend the abstract class myA. These classes have x fields of class B. The fields of class B are annotated with the annotation Test.(Test is available at runtime) How can i get the annotation Test and its value from inside a method of class B.
public class A1 extends myA{
#Test("all")
private B b1;
#Test("none")
private B b2;
#Test("none")
private B b3;
//....
public void interact(){
b2.doSomethingBasedOnMyAnnotation();
}
}
public class A2 extends myA{
#Test("none")
private B b;
//....
}
public class B{
public void doSomethingBasedOnMyAnnotation(){
// How to reach the Annotation from here ?
}
}
#Retention(value = RetentionPolicy.RUNTIME)
#Target(value = ElementType.FIELD)
public #interface Test{
String value() default "all";
}
When you place an annotation on a variable, it becomes a static property of that variable, not of the object you can reach through that variable. Consider:
public class A1 extends myA{
#Test("all")
private B b1=new B();
#Test("none")
private B b2=b1;
//....
public void interact(){
// this
b2.doSomethingBasedOnMyAnnotation();
// is exactly the same as
b1.doSomethingBasedOnMyAnnotation();
}
}
It’s not even valid to assume that there is an annotated variable involved. What about
new B().doSomethingBasedOnMyAnnotation()?
Since fields are resolved at compile-time, there is no abstraction in your desired operation anyway. If you know that you are going to invoke, b2.doSomethingBasedOnMyAnnotation();, you already know which field you’re using and there’s no problem of providing the annotation value of b2 as parameter to the invoked method, rather than expecting the receiver to magically find out. E.g.
public class B{
public void doSomething(String arg){
}
}
public class A1 extends myA{
#Test("all")
private B b1;
#Test("none")
private B b2;
//....
public void interact(){
b1.doSomething(get("b1"));
b2.doSomething(get("b2"));
}
static String get(String fieldName) {
try {
return A1.class.getDeclaredField(fieldName)
.getAnnotation(Test.class).value();
} catch(NoSuchFieldException ex) {
throw new IllegalStateException(ex);
}
}
}
though we could happily work without Reflection:
public class A1 extends myA{
static final String TEST_B1="all";
#Test(TEST_B1)
private B b1;
static final String TEST_B2="none";
#Test(TEST_B2)
private B b2;
static final String TEST_B3="none";
#Test(TEST_B3)
private B b3;
//....
public void interact(){
b1.doSomething(TEST_B1);
b2.doSomething(TEST_B2);
}
}
If you want to make sure that the caller can’t pass the wrong argument by accident, use encapsulation instead:
public final class EncapsulatedB {
final String testValue;
B b;
EncapsulatedB(String value) {
this(value, null);
}
EncapsulatedB(String value, B initialB) {
testValue=value;
b=initialB;
}
public B getB() {
return b;
}
public void setB(B b) {
this.b = b;
}
public void doSomething() {
b.doSomething(testValue);
}
}
public class A1 extends myA{
private final EncapsulatedB b1=new EncapsulatedB("all");
private final EncapsulatedB b2=new EncapsulatedB("none");
private final EncapsulatedB b3=new EncapsulatedB("none");
//....
public void interact(){
b1.doSomething();
b2.doSomething();
}
}
Related
I'm a beginner at Java so I don't know if what I'm trying to access is an upper/wrapper class. Basically, I have three classes, A, B and C.
CLASS A.java
public class A{
private String aName;
private B objectB;
}
CLASS B.java
public class B{
private String bName;
private C objectC;
}
CLASS C.java
public class C{
private String cName;
}
Basically, I have a Class A, which has an object of Class B, which in turn has an Object of class C.
I have an instance of an object of class C. How do I access the variables bName and cName from this instane of object C?
Why don't you use getter & setter method for accessing variable bName from instance of c. you can not directly access them as they are private.
"CLASS B.java"
public class B{
private String bName;
public String getbName() {
return bName;
}
public void setbName(String bName) {
this.bName = bName;
}
private C objectC;
}
You can directly access "cName" variable as this variable is the belong to same obejct of c which you are using to get bName.
The easiest solution for getting access to the instance of Class B from Class C would be to add a reference to B in C:
Class C
public class C {
private String cName;
private B bObj;
}
And then use getters and setters in class B:
Class B
public class B {
private String bName;
private C cObj;
public String getBName() {
return bName;
}
public void setBName(String newName) {
this.bName = newName;
}
}
However, do remember that this leads to a circular dependency, which usually is a code smell (it may be OK in this situation though, depending on the overall class hierarchy).
The better option would be to implement the Observer pattern between the classes:
Class C
public class C {
private String cName;
private List<Observers> observers; //if you only need one instance, then
//switch out for a single interface reference
public void requestWrapperName () {
List<String> names = new ArrayList<>();
for(observer: observers) {
names.add(observer.requestName());
}
// code to do what you want with wrapper name
...
}
public void addObserver(Observer observer) {
observers.add(obsersver);
}
}
Observer interface
public interface Observer {
String requestName();
}
Class B
public class B implements Observer {
private String bName;
private C cObj;
// Observer method
public String requestName() {
return bName;
}
}
Now, when you have the instance of C in class B, you can just inject B as an observer into C with cObj.addObserver(this); and then request B's name with the method requestWrapperName();. Thus avoiding having associations both ways :)
I have a class C with lots of members(say 10 members) + members that are only in C
I have two more classes A and B which has exactly those above mentioned 10 members. (A and B each does not have those 10 members. Those 10 members are distributed among A and B and A and B has few other fields)
class C {
private int member1;
private String member2;
private String member3;
private float member4;
...
private String member10;
private member11_only_in_C;
private member12_only_in_C;
...
}
class A {
private String memeber10;
private float member4;
private double member6;
....
}
class B {
private int memeber1;
private String memeber2;
private String member7;
....
}
So when I have cObject I need to set the values of all members in A and B like
aObject.setMember10(cObject.getMember10());
bObject.setMember1(cObject.getMember1());
... and so on for all 10 members
This looks bad(long and in future If i add more members to C,A,B I need to write setters for them). So what I thought was If I have class C extend or implement A and B I can cast it like
A aObject = (A)cObject;
B bObject = (B)cObject;
But the problems are
Java does not allow multiple inheritance
I cannot make A and B as interfaces because I need to set their values. (If I make them as interfaces, their members would become final, which means that I cannot change their values)
I cannot extend one class and implement other. (I then cannot set values of members of the interface)
What can I do now?
Thanks..
As I understand it you have two classes A and B, both with a number of fields, and you want to create a third class C with all the fields of A and B.
As you point out you can't do this with inheritance in Java because multiple inheritance of state is not supported.
You can do something similar using composition instead.
public final class C {
private final A a;
private final B b;
public C(A a, B b) {
this.a = a;
this.b = b;
}
...
void setMember7(String s) {
b.setMember7(s);
}
String getMember7() {
return b.getMember7();
}
...
}
I'm not sure if this is a good idea or what you need though. We would need more information about your use-case.
EDIT
If A and B have fields that are not in C you could make a class A2 with all the fields common to A and C and a class B2 with all the fields common to B and C, like this:
public final class A {
private final A2 a2;
// other fields
public A(A2 a2) {
this.a2 = a2;
}
}
public final class B {
private final B2 b2;
// other fields
public B(B2 b2) {
this.b2 = b2;
}
}
public final class C {
private final A2 a2 = new A2();
private final B2 b2 = new B2();
...
public void setMember7(String s) {
b2.setMember7(s);
}
public String getMember7() {
return b2.getMember7();
}
...
public A getA() {
return new A(a2);
}
public B getB() {
return new B(b2);
}
}
I don't know exactly what you want but i think what you need can be accomplished in the constructor
Class A{
private member1;
private member10;
Class A(){
}
Class A(C cObject){
member1 = cObject.getMember1();
//the rest of member varaibles you want to set
member10 = cObject.getMember10();
}
}
Class B{
private member1;
private member10;
Class B(){
}
Class B(C cObject){
member1 = cObject.getMember1();
//the rest of member varaibles you want to set
member10 = cObject.getMember10();
}
}
to use it :-
B objectB = new B(objectC);
A objectB = new A(objectC);
I have three classes.
Class A extends jFrame (Which is the main user interface)
Class B extends jPanel (This one is called to appear inside of the main jFrame)
and Class C to do some file handling and processing.
What I am trying to do is have an object of Class C instantiated in Class A and calling it in Class B.
Here's some sample code:
Public Class A extends javax.swing.JFrame {
Public A(){
C ObjectOfC = new C();
B panelWithButtons = new B();
}
}
public Class B extends javax.swing.JPanel{
String s = ObjectOfC.getName();
}
public Class C{
String name;
public String getName(){
return this.name;
}
}
Is there anyway to get this done? or is it a lost cause?
There are a number of ways to do this, depending on what you are trying to accomplish. You probably want to build either a constructor or a method for B that takes object C as an argument.
Example:
Public Class A extends javax.swing.JFrame {
Public A(){
C objectOfC = new C();
B panelWithButtons = new B(objectOfC);
}
}
public Class B extends javax.swing.JPanel{
String s;
public B (C objectOfC) {
this.s = objectOfC.getName();
}
}
public Class C{
String name;
public String getName(){
return this.name;
}
}
A singleton example as per your comment:
Public Class A extends javax.swing.JFrame {
Public A(){
B panelWithButtons = new B();
}
}
public Class B extends javax.swing.JPanel{
String s;
objectOfC C = C.getInstance();
this.s = objectOfC.getName();
}
public class C {
private static String name;
private static final C INSTANCE = new C();
private C() {}
public static C getInstance() {
return INSTANCE;
}
public static String getName() {
return this.name;
}
}
A singleton example with changing variables (and errors removed from the original code.):
public class A extends javax.swing.JFrame {
public A() {
C objectOfC = C.getInstance();
objectOfC.setName("Bob");
B panelWithButtons = new B(objectOfC);
System.out.println("objectOfC_A:" + objectOfC.getName()); //return "George"
}
}
public class B extends javax.swing.JPanel {
public B (C objectOfC) {
C c2 = C.getInstance();
objectOfC.setName("Fred");
c2.setName("George");
System.out.println("objectOfC_B:" + objectOfC.getName()); //returns "George"
System.out.println("c2: " + c2.getName()); //returns "George"
}
}
public class C {
private static String name;
private static final C INSTANCE = new C();
private C() {}
public static C getInstance() {
return INSTANCE;
}
public String getName() {
return C.name;
}
public void setName (String name) {
C.name = name;
}
}
With this example you can call C.getInstance from any class and they will all be sharing the same instance. However, you must be careful with how you are going to access the object; there are plenty of tutorials out there about multithreading singletons which you will need to do if you plan on modifying data in the C instance from multiple objects at the same time.
I have a class A, with a private member int myMember. And a class B with a private member of the class A, called myA;
That is:
public class A{
private int myMember;
...
}
public class B{
private A myA;
}
I would like to be able to access:
B.myA.myMember;
but it seems I can't because myMember is private in A. The thing is, I need A to be defined as private for the purpose of the exercise (that also includes it can't be protected). Is there a way around this?
Thanks.
public class A {
private int myMember;
public int getMyMember() {
return myMember;
}
public void setMyMember(int myMember) {
this.myMember = myMember;
}
}
public class B{
private A myA;
public B() {
myA = new A();
myA.setMyMember(0);
int a = myA.getMyMember();
}
}
Use getters :
public class A {
private int myMember;
public getMyNumber() {
return myNumber;
}
}
public class B {
private A myA;
public A getA() {
return myA;
}
}
So now you can code :
B b = new B();
b.getA().getMyMember();
Since you've stated you can't create more public methods, aka getters, you could use reflection...
public class A{
private int myMember;
...
}
public class B{
private A myA;
private int get(){
try {
Field field = myA.getClass().getDeclaredField("myMember");
field.setAccessible(true);
return (int) field.get(myA);
catch (Exception e){
//Something went wrong, the field doesn't exist or a security exception
return null; //or return some "error number" like -10
}
}
}
If you can declare the private field as static then something like this is possible :
public class A {
private int myMember;
}
public class B {
public static void main (String[] args) {
int myMember = new A() {
public int getPrivate() {
return myMember;
}
}.getPrivate();
System.out.print("\n\t Id : " + myMember);
}
}
Suppose I have a class A and a class B.
public class A {
private B b;
public A() {
this.b = new B();
}
public B getB() {
return this.b;
}
}
public class B {
public String getSome() {
return "Get some!";
}
}
I know I can get B through A, because A has (or owns) B: new A().getB().
But if I have B, can I get A?
Sure, just add routine getA() in you class B, and change the line in your constructor to
public A() {
this.b = new B(this);
}
This of course assumes your class B has a constructor which accepts an A, e.g.,
public B(A a) {
this.a = a;
}
B needs an explicit reference to its owner:
public class B {
private final A owner;
public B(A owner) {
this.owner = owner;
}
public A getOwner() {
return owner;
}
}
And in A:
public A() {
b = new B(this);
}
Nope. There is no such thing as an 'owner' in Java. Any object can be referenced by any number of other objects.
If you need B to always be bound to an instance of A, make B an inner class of A:
class A {
B b = new B();
class B {
String getSome() {
// this will refer to the enclosing A
return A.this.toString();
}
}
}
An inner (non-static) class always has an implicit reference to the enclosing instance and cannot exist without it. In order to instantiate B from outside, you need a nasty syntax: B b = new A().new B();
No you cannot. B has no reference to A.
No.
Class a has reference to class B, but class B has no reference to class A. References are one way only.
No, that's not possible. You're looking for backreferences, but we have to create them in the code if needed.
If you want to collect all referencers to B, you could do this with a constructor or with a factory (pattern) that creates B's. I'll show the factory:
public class B {
private static Set<? extends Object> referencers = new HashSet<? extends Object>();
private B(){} // no public constructor
public static create(Object parent) {
// cooperative approach, the caller should pass "this"
referencers.add(parent);
}
public static remove(Object parent) {
referencers.remove(parent);
}
}
you can also use inner classes
package test;
public class A {
B b = null;
public B getB()
{
return b;
}
public class B {
public A getA()
{
return A.this;
}
}
public static void main(String[] args) {
B b = new A().new B();
}
}