Suppose i have classes A,B,C. C has a method longRunningMethod, which takes a long time to run and returns an int. Classes A and B both have C as a dependency and need to call method longRunningMethod:
public class A{
private C c;
public A(C c){
this.c = c;
}
public void method1(){
this.c.longRunningMethod();
}
}
public class B{
private C c;
public A(C c){
this.c = c;
}
public void method2(){
this.c.longRunningMethod();
}
}
public class C{
public int longRunningMethod(){
...
}
}
public class MyProgram{
public static void main(String[] args){
C c = new C();
A a = new A(c);
B b = new B(c);
a.method1();
b.method2()//avoid calling c.longRunningMethod();
}
}
What approaches can be taken to avoid calling longRunningMethod twice? Of course, the simple approach is to change the constructor argument of A and B to int and call longRunningMethod once in MyProgram. But then, it is not that obvious to what to pass to A and B (which ints are allowed?).
public class C{
private boolean wasCalled = false;
private int cachedValue;
public int longRunningMethod(){
if (!wasCalled) {
// do your long running job here and set result to cachedValue
wasCalled = true;
}
return cachedValue;
}
}
Related
I have 3 Data Classes
#Data
class A
{
private int a;
}
#Data
class B extends A
{
private int b;
}
#Data
class C extends A
{
private int c;
}
Class B and C have some common fields between them which is kept in their parent class A.
Following is the tester class
class TesterClass
{
static String bOrC = "C"; // input from some decision
public static void main(String[] args) // assume this to be the client
{
A a;
if (bOrC.equals("B")) {
B b = new B();
b.setB(11);
a = b;
} else {
C c = new C();
c.setC(12);
a = c;
}
a.setA(10);
doSomething(bOrC, a);
}
// Below are the service methods
// only this method in the service exposed
public static void doSomething(String bOrC, A a) {
if (bOrC.equals("B")) {
doSomethingWithB(a);
} else if (bOrC.equals("C")) {
doSomethingWithC(a);
}
}
public static void doSomethingWithB(A a) {
B b = (B) a; // possible ClassCastException
System.out.println(b.getA());
System.out.println(b.getB());
}
public static void doSomethingWithC(A a) {
C c = (C) a; // possible ClassCastException
System.out.println(c.getA());
System.out.println(c.getC());
}
}
Now the problem I see with this is unsafe Dynamic Type Casting which can run into Class Cast Problems. One possible solution would be to create separate data objects and set the common fields (which are too many for my actual case) for both the objects separately in both classes B and C which would then look as follows:
public class TesterClass
{
static String bOrC = "C"; // input from some decision
public static void main(String[] args)
{
if (bOrC.equals("B")) {
B b = new B();
b.setA(10); // duplication
b.setB(11);
doSomethingWithB(b);
} else {
C c = new C();
c.setA(10); // duplication
c.setC(12);
doSomethingWithC(c);
}
}
public static void doSomethingWithB(B b) {
System.out.println(b.getA());
System.out.println(b.getB());
}
public static void doSomethingWithC(C c) {
System.out.println(c.getA());
System.out.println(c.getC());
}
}
I'm looking for a way to avoid this dynamic type casting but at the same time avoid having to duplicate the common variables. Can anyone suggest a solution?
Abstraction is one solution for the behavior you are explaining. Creating an abstract method doSomething(...) in class A and implementing it in child class B and C respectively. By doing this you don't need to have a static method and processing will be done bases on the instance of B or C objects itself.
#Data
class A
{
private int a;
public abstract void doSomething();
}
#Data
class B extends A
{
private int b;
public void doSomething(){
/*.... do something here
* here you can also access parent public methods and properties.
* as you have already annotated with #Data you will have access to getA() method, * hence you can also use parent properties.
*/
}
}
#Data
class C extends A
{
private int c;
public void doSomething(){
/*.... do something here
* here you can also access parent public methods and properties.
* as you have already annotated with #Data you will have access to
* getA() method, * hence you can also use parent properties.
*/
}
Now you can use it as below
public static void main(Strings[] args){
A a;
B b = new B();
b.setB(10);
b.doSomething();
C c = new C();
c.setC(30);
c.doSomething();
}
I've been using multiple methods, but my "java the complete reference" book doesn't do a good job of explaining how to use the "this" keyword.
this in java
It is used to refer to the data members of the object in the envoked method or constructor in case there is a name conflict between fields and local variables
public class Test {
String s;
int i;
public Test(String s, int i){
this.s = s;
this.i = i;
} }
It is used to invoke one constructor from another constructor of the same class or you can say constructor chaining.
public class ConstructorChainingEg{
String s;
int i;
public ConstructorChainingEg(String s, int i){
this.s = s;
this.i = i;
System.out.println(s+" "+i);
}
public ConstructorChainingEg(){
this("abc",3); // from here call goes to parameterized constructor
}
public static void main(String[] args) {
ConstructorChainingEg m = new ConstructorChainingEg();
// call goes to default constructor
}
}
It also facilitates method chaining
class Swapper{
int a,b;
public Swapper(int a,int b){
this.a=a;
this.b=b;
}
public Swapper swap() {
int c=this.a;
this.a=this.b;
this.b=c;
return this;
}
public static void main(String aa[]){
new Swapper(4,5).swap(); //method chaining
}
}
Here's a couple:
public class Example {
private int a;
private int b;
// use it to differentiate between local and class variables
public Example(int a, int b) {
this.a = a;
this.b = b;
}
// use it to chain constructors
public Example() {
this(0, 0);
}
// revised answer:
public int getA() {
return this.a;
}
public int getB() {
return this.b
}
public int setA(int a) {
this.a = a
}
public void setB(int b) {
this.b = b;
}
}
this refers to the attributes that belong to the object in which this is used in. For example:
Example ex1 = new Example(3,4);
Example ex2 = new Example(8,1);
In these cases, ex1.getA() will return 3, because this is referring to the a that belongs to the object named ex1, and not ex2 or anything else. The same goes for ex2.getB().
If you look at the setA() and setB() methods, using this distinguishes the attributes a and b belonging to the object from the parameter names as they're the same.
Code:
public class A{
B b = new B();
public class B{
public void fun(){ send(A); }
}
I want to do something with all A object in B.
I can create method in A class:
private A getThis(){return this;}
But is it other solution (some keyword)?
Try this code inside your inner class.
A.this
It should give you a reference to the enclosing instance from the outer class.
Here is a small example.
public class A {
private B b = new B();
public class B {
public void fun() {
}
public A getEnclosing(){
return A.this;
}
}
public static void main(String[] args){
A a = new A();
System.out.println(a == a.b.getEnclosing());
}
}
Try
B b = new B(this);
Then B contructor
public B(A a) {
this.a = a;
}
I am pretty new to google guice .
I am writing a nexus plugin where nexus injects some classes . for example say the class to be injected in class A.
Now before that class A is injected, I have another class B that was instantiated and inside it I have a method where an object (say obj) is initialised .
I have to pass this initialised object to the class A.
Normally if instantiation is under our control I will do as
A a = new A();
A.setObject(obj);
But now given that the class will be injected by the system , I don't know how to pass this initialised object to this class A.
If I understand correctly, you have something like
public class C {
}
public class A {
private C c;
public void setC(C c) {
this.c = c;
}
}
public class B {
private final C c;
public B() {
this.c = new C();
}
public C getC() {
return this.c;
}
}
public class Main {
public static void main(String[] args) {
B b = new B();
A a = new A();
C c = b.getC();
a.setC(c);
}
}
This design does not follow DI principles and should be refactored. You should let Guice create your C instance. In that case you will have something like
public class C {
}
public class A {
private final C c;
#Inject
A(C c) {
this.c = c;
}
}
public class B {
private final C c;
#Inject
B(C c) {
this.c = c;
}
}
public class Main {
public static void main(String[] args) {
Injector injector = Guice.createInjector();
A a = injector.getInstance(A.class);
B b = injector.getInstance(B.class);
}
}
And here you have C automatically injected both into A and B.
If you really cannot refactor you code, consider using providers then:
public class AProvider extends Provider<A> {
private final B b;
#Inject
AProvider(B b) {
this.b = b;
}
#Override
public A get() {
A a = new A();
C c = b.getC();
a.setC(c);
// Or, better
// A a = new A(b.getC());
return a;
}
}
public class Main {
public static void main(String[] args) {
Injector injector = Guice.createInjector(new AbstractModule() {
#Override
protected void configure() {
bind(A.class).toProvider(AProvider.class);
}
});
A a = injector.getInstance(A.class);
}
}
In this case a provider is used to create A and set its C dependency.
But sometimes even that is not enough (e.g. when your B.getC() behavior depends on user input). In that case you have to use assisted inject extension:
public interface AFactory {
public A create(C c);
}
public class A {
private final C c;
private final Other other;
#Inject
A(#Assisted C c, Other other) {
this.c = c;
this.other = other;
}
}
public class Main {
public static void main(String[] args) {
Injector injector = Guice.createInjector(new AbstractModule() {
#Inject
protected void configure() {
install(new FactoryModuleBuilder()
.build(AFactory.class));
}
});
B b = injector.getInstance(B.class);
C c = b.getC(someUserInput);
AFactory af = injector.getInstance(AFactory.class);
A a = af.create(c);
}
}
In the last example two object will be injected into A via af.create(c) invocation: first, that c you have provided, and second, and instance of Other class which is resolved automatically by Guice. In other words, assisted inject allows you to instantiate classes which will have one part of their dependencies resolved by you, and other part - by Guice.
I'm using Java and I want to call the method f2 in class A from the class B. Is it possible to do this?
public class A{
private B b = new B();
public void f1(){
b.f3();
}
public void f2(){
// do something;
}
}
public class B{
public void f3(){
// Call f2 of class A from here.
}
}
You need an instance of A in class B and invoke f2 on that instance. For example, you could instantiate one inside the body of f3:
public class B {
public void f3() {
A a = new A();
a.f2();
}
}
Another way would be for f3 to receive an instance of A:
public class B {
public void f3(A a) {
a.f2();
}
}
And yet another way, you could have B instantiate one:
public class B {
private final A a;
public B() { this.a = new A(); }
public void f3() {
this.a.f2();
}
}
And lastly, B could receive one in it's constructor:
public class B {
private final A a;
public B(A a) { this.a = a; }
public void f3() {
this.a.f2();
}
}
The point being that if you want to invoke an instance method on a class you must have an instance of that class in your hand.
Finally, I notice that you have A.f1 invoking B.f3 and from there you want to invoke A.f2. So, it looks like your best option here is the second option above. That is:
public class A {
private final B = new B();
public void f1() { this.b.f3(this); }
public void f2() { /* do something */ }
}
public class B {
public void f3(A a) { a.f2(); }
}
The key here is that we are passing an instance of A to B.f3. The way that we achieve that is by passing the this reference, which is a reference to the currently executing instance. In A.f1, that would be the instance of A that is currently executing.
You need an instance of class A to do this.
public class A{
private B b = new B();
public void f1(){
b.f3(this);
}
public void f2(){
// do smthing;
}
}
public class B{
public void f3(A a){
a.f2(); // Call f2 of class A from here.
}
}
This type of code structure is usually more confusing than useful. I suggest instead doing this.
public class A{
private B b = new B();
public void f1(){
WhatAf2Needs w = b.f3();
f2(w);
}
public void f2(WhatAf2Needs w){
// do smthing;
}
}
public class B{
public WhatAf2Needs f3(A a){
return WhatAf2Needs;
}
}
If you want to call a method of the thing that called you, you have to have the caller pass itself in using the this keyword. In code, it would be:
public class A{
private B b = new B();
public void f1(){
b.f3(this);
}
public void f2(){
// do smthing;
}
}
public class B{
public void f3(A caller){
caller.f2();
}
}
You would have to instantiate class A in class B, given the way it's currently written, to make any method calls on it.
You can also declare f2 static and call it like A.f2(). This type of things depend a lot on the design of your classes though. The other answers here are very valid too.
public class A{
private B b = new B();
public void f1(){
b.f3();
}
public static void f2(){
// do smthing;
}
}
public class B{
public void f3(){
A.f2();
}
}