Mixing data in abstract class when working in parallel - java

I have a problem with my abstract class, I have an app for about 2000 users and many make calls at the same time to different classes, those classes share an abstract class
class A extends B{
//Code
}
The inconvenience arises when in my abstract class I receive parameters to some of my methods that in this case all classes call these methods.
class abstract B {
public int getResult(int b){
return b+1;
}
}
class C extends B {
public int getValue(int a){
int b = getResult(a);
int c = b * 2 / 4;
return c + 150;
}
}
When several people in parallel enter the class 'C' and pass different parameters to the method getResult ends up mixing the data sent and returns erroneous data in the execution.
The option that I have found is to implement the getResult method in each class, but that makes me repeat code in each class and there are about 200 classes that implement that abstract class
I've read that with encapsulation I can avoid that, but I don't know if that's the option since I haven't worked on it.
I have used the synchronized but it has created many bottlenecks and response times have increased.

I think you need use synchronized in your getValue method to manage parallel access to yout method. Maybe this article can help you, have a simple example too: https://dzone.com/articles/java-concurrency-synchronization#:~:text=the%20credit%20method
Note B class must have _"abstract" keyword before class.
Add "synchronized" in your getValue method
This way:
abstract class B {
public int getResult(int b){
return b+1;
}
}
class C extends B {
public synchronized int getValue(int a){
int b = getResult(a);
int c = b * 2 / 4;
return c + 150;
}
}

Related

Avoid code duplication over classes

I am writing some classes and all of them implement a certain method they inherit from an interface. This method is close to the same for all the classes beside one call to a certain other function.
For example:
public void doSomething(){
int a = 6;
int b = 7;
int c = anOtherMethod(a,b);
while(c < 50){
c++;
}
}
What if multiple classes have the function doSomething() but the implementation of the method anOtherMethod() is different?
How do I avoid code duplication in this situation? (This is not my actual code but a simplified version that helps me describe what I mean a bit better.)
This looks like a good example of the template method pattern.
Put doSomething in a base class.
Declare abstract protected anotherMethod in that base class as well, but don't provide an implementation.
Each subclass then provides the proper implementation for anotherMethod.
This is how you could implement the technique that Thilo talked about in the following demo:
Main class:
public class Main extends Method {
public static void main(String[] args) {
Method m = new Main();
m.doSomething();
}
#Override
public int anOtherMethod(int a, int b) {
return a + b;
}
}
Abstact class:
public abstract class Method {
public abstract int anOtherMethod(int a, int b);
public void doSomething() {
int a = 6;
int b = 7;
int c = anOtherMethod(a, b);
System.out.println("Output: "+c);
}
}
This way, all you have to do is override anOtherMethod() in each class that you want to use doSomething() with a different implementation of the method anOtherMethod().
Assuming every version of anOtherFunction takes two integers and returns an integer, I would just have the method accept a function as an argument, making it Higher Order.
A function that takes two arguments of the same type and returns an object of the same type is known as a BinaryOperator. You can add a argument of that type to the method to pass a function in:
// Give the method an operator argument
public void doSomething(BinaryOperator<Integer> otherMethod) {
int a = 6;
int b = 7;
// Then use it here basically like before
// "apply" is needed to call the passed function
int c = otherMethod.apply(a,b);
while(c < 50)
c++;
}
}
How you use it though will depend on your use case. As a simple example using a lambda, you can now call it like:
doSomething((a, b) -> a + b);
Which simply returns the sum of a and b.
For your particular case though, you may find that having doSomething as part of a Interface isn't necessary or optimal. What if instead, anOtherMethod is what's required to be supplied? Instead of expecting your classes to supply a doSomething, have them supply a BinaryOperator<Integer>. Then, when you need to get results from doSomething, get the operator from the class, then pass it to doSomething. Something like:
public callDoSomething(HasOperator obj) {
// There may be a better way than having a "HasOperator" interface
// This is just an example though
BinaryOperator<Integer> f = obj.getOperator();
doSomething(f);
}

Casting a class into another non hierarchical class form in java

Consider class A
class A {
int i;
int j;
int k;
}
and here is the class B
class B {
int a;
int b;
int c;
}
I was wondering if java has any such ting which allows to write/define our own custom casting logic.
For e.g.
to cast class B's object into class A's object where
i -> a // i pointing to value of a
j -> b // j pointing to value of b
k -> c // k pointing to value of c
(I can customize the logic to whatever i wish)
I have a few heavy weight objects to "cast" into some other classes to use and i do not want to write a converter method for this.
(casting operates only on the object in consideration and does not create another object)
any thoughts/suggestions for this ?
Thanks in Anticipation !
You can use the frameworks like ModelMapper (documentation) to define your maping logic and use it to convert object from one type to object of another type. E.g. this is how the configuration would be:
//Model Classes
class A{
int a;
}
class B{
int d;
}
//Mappings
PropertyMap<A, B> map = new PropertyMap<A, B>() {
protected void configure() {
map(source.a, destination.d);
}
};
//Test Program
public static void main(String[] args) throws Exception {
ModelMapper mapper = new ModelMapper();
PropertyMap<A, B> map = new PropertyMap<A, B>() {
protected void configure() {
map(source.a, destination.d);
}
};
mapper.addMappings(map);
A a = new A();
a.a = 10;
B b = mapper.map(a, B.class);
System.out.println(b.d);
}
This defeats the safety purposes of Java for two reasons.
Let's consider an updated version of your class code.
class A {
int i;
int j;
int k;
int l;
}
class B {
int a;
int b;
int c;
}
Now imagine what would happen if you did something like this, assuming the classes were written right above: (Warning:code will not compile)
public static void main(String[] args)
{
B classTwo = new B();
A classOne = (A) classTwo;
classOne.l = 3; // <-- what would happen?
}
As you can see, it won't work, because creating an instance of B will not allocate the variabls properly. This is why Java does not permit casting like that.
What Java does permit is converting between superclasses and subclasses.
For example:
class Fruit {
int i;
}
class Apple extends Fruit {
int j;
}
And now inside the main function:
Fruit f = new Fruit();
Apple a = (Apple)f; // this compiles, but will raise a ClassCastException
You'll ask, why does it raise a ClassCastException? Apple extends Fruit.
Yes, Apple extends Fruit. But, Fruit does not allocate memory for the j variable.
What is allowed is the other way around, casting an Apple to a Fruit, because all Apples have properties of Fruits (even in real life).
If you want to use your idea of casting, you could try an interface.
interface C {
public int getVarOne();
public int getVarTwo();
// NO variables here, only functions
}
Any class which implements (not extends) an interface must also implement all of the methods defined in it.
Once you've implemented the interface, the behavior is similar to casting to a superclass. There are also other uses for interfaces, but that is beyond the scope of this question.
No. There's no such thing as unions known from C. You cannot modify the memory directly in JVM. That's the point of Java. It sacrifices some potential for tricks, but in the end the code tends to be less buggy and easier to maintain than the code written in C.
If your concern is memory consumption caused by copying, you can convert A and B into interfaces. The interfaces should expose getters and setters. For example: int getI() and int getA(). Then you can introduce a class implementing both of them.
The indirection caused by the interface calls will have some performance cost, but in many cases, it won't be noticable.

How to reference a shadowed variable in the superclass of a superclass?

This is a simple example of inheritance where there is a shadowed variable x.
class A{
int x=1;
}
class B extends A{
int x=2;
}
class C extends B{
int x=3;
int y;
}
How can I reference the shadowed variable x of class A in class C?(I want something like y=super.super.x; that works well.)
Not as hard as you might think. (While I strongly encourage avoiding this situation,) if you have a class C that inherits from class B, which in turn inherits from class A, all of which implement a public field x, then using super is usually the wrong way to go about it.
Instead, given class C, try this:
((A)this).x; //don't forget the parentheses!
that will give you the value of x for A. Also,
super.x == ((B)this).x;
which is generally why, for single steps, we usually just use super.
Hopefully that helps.
To my knowledge, there is no way to achieve this the way you imagine. Your best bet would be to implement an access method in your class B:
class B extends A{
int x=2;
protected int getXFromA() {
return super.x;
}
}
This way you would be able to access the value of x as defined in class A from class C.
I would be very interested in your use case, though. Considering object oriented design, what reason could there be to directly access A's members from C? If this is the case, from an OOP perspective, C could not really be considered a proper subclass of B anymore.
class A {
int x = 1;
}
class B extends A {
int x = 2;
}
class C extends B {
int x = 3;
int y = ((A) this).x;
}
Note that shadowing is generally discouraged due to the confusion it can cause.

Basic Java inheritance exercise

I'm learning Java and I'm doing this exercise and I have to say what the main method prints. Its goal is to better understand Java inheritance.
interface X extends Remote{
A m(B bb) throws RemoteException;
}
class A implements Serializable{
int a;
A m(A aa){
aa.a = 3;
System.out.println("A.m");
return aa;
}
}
class B extends A{
int b;
A m(B bb){
bb.b = 7;
System.out.println("B.m");
return bb;
}
}
class C extends A implements X{
public B m(B bb){
if(bb.b == 7) bb.b = 9; else bb.b = 1;
System.out.println("C.m");
return bb;
}
}
Now I have a main method in which I call:
X x = new C();
B b = new B();
(x.m(b)).m(b); // prints C.m() A.m()
The third line of my main method, prints "C.m() A.m()" but I don't understand why it prints A.m(). The x.m(b) returns an object that has both static and dynamic type == B; on this object it is invoked m(b) method; so why it is not called the m() method of B class?
I've seen that the m() mehtod in B class is not an overriding of the m() method in A class because they have different explicit parameter.
thanks in advance
b in an instance of B, which extends A. As such, B has 2 m methods.
To know which is called, what is important is the type of the object on which the method is called.
(x.m(b))
is the result of the call to the m method from the X interface, because the declaring type of x is X.
Therefore (x.m(b)) is an object of type A (even though the actual implementation is a B).
This being a type A, the m method from the A class is called.
If you change the names of the methods, it will become clearer that the m methods from A and B are really different objects.
Your mistake is assuming that
The x.m(b) returns an object that has both static and dynamic type == B;
Which is wrong, because x is declared of type X, making the result of x.m a type A.

Class-specific method visibility

Is there some object oriented thing that you can call some methods from certain classes, but not all of them? Is there something like that which is similiar to protected?
Say you have a method void foo() and you want it to be available to the programmer in a few types of classes (perhaps something like using Type variables (to specify: T type). Now, perhaps is there some way, without inheriting the class with foo() in it, or making an interface, to specify which classes or types of classes have access to that method?
I would guess this could be like multiple-inheritance and polymorphism? But I still want only the class and certain classes to access the method without changing the visibility of the method. I want the visibility to be class-specific.
Here is an example:
class A sees foo() as private, but only that class sees it as private.
class B sees foo() as public/protected, but only that class sees it as public.
The method type would be default.
I guess what is easier to ask and answer to is: "Is there class-specific visibility?"
There is something like you are asking for in C++, it is called friend classes. Nevertheless, that concept is not supported by Java:
'Friends' equivalent for Java?
A second option is to use code reflection to access a class private members but it isn't such a clean solution and only works for protected elements:
public class C1 {
public C1()
{
x = "Hello Word!";
}
protected String x;
}
At a different class's method:
String val = (String)obj.getClass().getDeclaredField("x").get(obj);
System.out.println("val: " + val);
EDIT: After making a little bit of research I found it is possible even to access private members:
Field field = obj.getClass().getDeclaredField("x");
field.setAccessible(true);
String val = (String)field.get(obj);
field.setAccessible(false);
No, there's nothing like that in Java.
The closest you've got is putting classes within the same package, at which point they have access to any members which don't specify any access modifier. You can't specify particular classes though.
Another option which is appropriate in some cases is to use nested classes:
class Outer {
private static class Inner {
}
}
Here Outer and Inner have access to each other's private members.
Access Levels
Modifier Class Package Subclass World
public Y Y Y Y
protected Y Y Y N
no modifier Y Y N N
private Y N N N
thats your lot, there are not any other access modifiers.
With a little sleight of hand you can make one class seem to be two different classes:
// An interface.
interface A {
public void a ();
}
// Another interface.
interface B {
public void b ();
}
// Deliberately NOT stating we implement either A or B but actually we implement both.
class C {
public void a () {
}
public void b () {
}
}
// Pick either implementation from C and tell the world about it.
class D extends C implements A {
// Do nothing - already done by C.
}
class E extends C implements B {
// Do nothing - already done by C.
}
public void test() {
A d = new D();
B e = new E();
}
Here D and E are actually identically functioned objects because they are both actually Cs. However, as they are created they are made to seem to be A or B which are two different interfaces.
Unfortunately we cannot hide the fact that they both extend C but a little further sleight of hand and we can do that too with a Factory.
// Hide the guts of it all in a factory.
static class Factory {
// Make sure you MUST use the factory methods.
private Factory () {
}
// Construct an A.
public static A newA () {
return new D();
}
// Construct a B.
public static B newB () {
return new E();
}
}

Categories

Resources