I have two (sibling) classes, both is subclass of the same parent. Parent contains all the methods that is shared by the two sibling, and the sibling classes contain only methods that are not shared and has different implementations.
Example,
class Parent() {
}
class Sibling1 extends Parent() {
byte[] sharedSecret;
int sharedSecretLength;
public generateKey() {
sharedSecret = keyAgree.generateSecret());
sharedSecretLength = sharedSecret.length);
}
}
class Sibling2 extends Parent() {
byte[] sharedSecret2;
int sharedSecretLength2;
public generateKey() {
sharedSecret2 = new byte[sharedSecretLength];
sharedSecretLength2 = keyAgree.generateSecret(sharedSecret2, 0);
}
public int getSharedSecretLength() {
return sharedSecretLength();
}
}
As you can see, both contains same method but implemented differently. My question is, if objects of both class (sibling1 and sibling2) are created AND obj2 generateKey to be generated successfully depends on sharedSecretLength of obj1. Example,
Parent obj1 = new Sibling1();
Parent obj2 = new Sibling2();
obj1 is instantiated in different class (Server class that I created) and obj2 in different class (Client that I created). If obj1 invoke it's own generateKey --> ((Sibling1)obj1).generateKey(), how can I use use getSharedSecretLength on the same object (obj1) to relay the needed information over to obj2's generateKey to generate successfully? I tried something like (in obj2's generateKey() ):
sharedSecret2 = new byte[Sibling1.sharedSecretLength];
...and it didn't work. Creating Sibling1 obj1 inside of Sibling2 class and then call it that way, for example,
Sibling1 xx = null;
.
.
sharedSecret2 = new byte[((Sibling1)xx).sharedSecretLength];
doesn't work because xx is new object. I am trying to use the old obj in which it generated it's key and contains sharedSecretLength that is not 0
If both obj1 and obj2 were created in the same class, it would have been easier.
Please help point me to the right direction
Instead of
((Sibling1)xx).sharedSecretLength
call it like
((Sibling1)xx).getSharedSecretLength()
In java, you have pass the empty parenthesis if it doesn't accept parameter and it doesnt work by field name, you will have to give the same method name as to what you have defined.
It sounds like you should refactor like this so that the generateKey method on Sibling2 has the argument it requires:
Sibling1 obj1 = new Sibling1();
obj1.generateKey();
Siblibg2 obj2 = new Sibling2();
obj2.generateKey(obj1.getSharedSecretLength());
Related
I am developing a Java application based on JavaParser. I do not know how to get class name of Super keyword used in a method body. As an example, I need to know Super keyword in the below code is referred to class A.
class A {
public void bar(){...}
}
class B extends A {}
class C extends B {
void foo(){
super.bar() // I want to find that the super keyword is referred to Class A.
}
}
I checked these functions (1, 2, and 3) provided by JavaParser, but none of them worked, all return null.
MethodCallExpr methodCallExpr = ...
Optional<Expression> scope = methodCallExpr.getScope();
SuperExpr superExp = scope.get().asSuperExpr();
1. superExp.findAll(ClassOrInterfaceDeclaration.class); and
2. superExp.getTypeName();
3. superExp.getClassExpr(); //I do not know why this method also returns null
I find the right method.
ResolvedType resolvedType = superExp.calculateResolvedType();
This method works correctly if you also add the JavaSymbolSolver to the parser configuration. JavaSymbolSolver is necessary to resolve references and find relations between nodes.
TypeSolver reflectionTypeSolver = new ReflectionTypeSolver();
TypeSolver javaParserTypeSolver = new JavaParserTypeSolver(projectSourceDir);
CombinedTypeSolver combinedSolver = new CombinedTypeSolver();
combinedSolver.add(reflectionTypeSolver);
combinedSolver.add(javaParserTypeSolver);
ParserConfiguration parserConfiguration = new ParserConfiguration()
.setSymbolResolver(new JavaSymbolSolver(combinedSolver));
SourceRoot sourceRoot = new SourceRoot(projectSourceDir.toPath());
sourceRoot.setParserConfiguration(parserConfiguration);
I was looking as the question : Instantiate a class from its string name which describes how to instantiate a class when having its name. Is there a way to do it in Java? I will have the package name and class name and I need to be able to create an object having that particular name.
Two ways:
Method 1 - only for classes having a no-arg constructor
If your class has a no-arg constructor, you can get a Class object using Class.forName() and use the newInstance() method to create an instance (though beware that this method is often considered evil because it can defeat Java's checked exceptions).
For example:
Class<?> clazz = Class.forName("java.util.Date");
Object date = clazz.newInstance();
Method 2
An alternative safer approach which also works if the class doesn't have any no-arg constructors is to query your class object to get its Constructor object and call a newInstance() method on this object:
Class<?> clazz = Class.forName("com.foo.MyClass");
Constructor<?> constructor = clazz.getConstructor(String.class, Integer.class);
Object instance = constructor.newInstance("stringparam", 42);
Both methods are known as reflection. You will typically have to catch the various exceptions which can occur, including things like:
the JVM can't find or can't load your class
the class you're trying to instantiate doesn't have the right sort of constructors
the constructor itself threw an exception
the constructor you're trying to invoke isn't public
a security manager has been installed and is preventing reflection from occurring
MyClass myInstance = (MyClass) Class.forName("MyClass").newInstance();
Using newInstance() directly is deprecated as of Java 8. You need to use Class.getDeclaredConstructor(...).newInstance(...) with the corresponding exceptions.
To make it easier to get the fully qualified name of a class in order to create an instance using Class.forName(...), one could use the Class.getName() method. Something like:
class ObjectMaker {
// Constructor, fields, initialization, etc...
public Object makeObject(Class<?> clazz) {
Object o = null;
try {
o = Class.forName(clazz.getName()).newInstance();
} catch (ClassNotFoundException e) {
// There may be other exceptions to throw here,
// but I'm writing this from memory.
e.printStackTrace();
}
return o;
}
}
Then you can cast the object you get back to whatever class you pass to makeObject(...):
Data d = (Data) objectMaker.makeObject(Data.class);
use Class.forName("String name of class").newInstance();
Class.forName("A").newInstance();
This will cause class named A initialized.
Use java reflection
Creating New Objects
There is no equivalent to method invocation for constructors, because invoking a constructor is equivalent to creating a new object (to be the most precise, creating a new object involves both memory allocation and object construction). So the nearest equivalent to the previous example is to say:
import java.lang.reflect.*;
public class constructor2 {
public constructor2()
{
}
public constructor2(int a, int b)
{
System.out.println(
"a = " + a + " b = " + b);
}
public static void main(String args[])
{
try {
Class cls = Class.forName("constructor2");
Class partypes[] = new Class[2];
partypes[0] = Integer.TYPE;
partypes[1] = Integer.TYPE;
Constructor ct
= cls.getConstructor(partypes);
Object arglist[] = new Object[2];
arglist[0] = new Integer(37);
arglist[1] = new Integer(47);
Object retobj = ct.newInstance(arglist);
}
catch (Throwable e) {
System.err.println(e);
}
}
}
which finds a constructor that handles the specified parameter types and invokes it, to create a new instance of the object. The value of this approach is that it's purely dynamic, with constructor lookup and invocation at execution time, rather than at compilation time.
Class.forName("ClassName") will solve your purpose.
Class class1 = Class.forName(ClassName);
Object object1 = class1.newInstance();
String str = (String)Class.forName("java.lang.String").newInstance();
something like this should work...
String name = "Test2";//Name of the class
Class myClass = Class.forName(name);
Object o = myClass.newInstance();
I am not sure what the best practice for downcasting from parent to child or creating a B (extends A) out of A is.
As an example I have two classes:
The parent one:
public class SoccerPlayer {
private String name;
private SoccerShoe shoe;
private SoccerJersey jersey;
/* ... */
}
And the child one:
public class Goalkeeper extends SoccerPlayer {
private GoalkeeperGlove glove;
/* ... */
}
Now a regular soccer player wants to be a Goalkeeper. What can I do? Obviously the following would not work:
SoccerPlayerArrayOfTeamA[0] = new SoccerPlayer("Robert");
/*... new career path ...*/
SoccerPlayerArray[0] = (Goalkeeper) SoccerPlayerArray[0]
But that is what I would say "I want to do"...
The new Instance of the child class (Goalkeeper) should have all variable configurations as the old Instance of the parent class (SoccerPlayer). (e.g. name, jersey ...)
Is there an OOP way to do that I do I have to set every variable manually as in the following?
/*... new career path ...*/
SoccerPlayer temp = SoccerPlayerArray[0]
SoccerPlayerArray[0] = new Goalkeeper(temp.getName());
SoccerPlayerArray[0].setJersey(temp.getJersey());
Checkout Decorator Design Pattern. E.g. Java IO classes.
When any object dynamically wants to change its behavior then you can wrap that object with the desired object. Like if C wants to become B then B should have a constructor which accepts C and then the methods in B should use C where ever appropriate. Best example is when FileInputStream wants to become BufferedInputStream you can just create BufferedInputStream by passing FileInputStream in its constructor but it does not need to copy properties of FileInputStream.
Add a copy constructor to Goalkeeper that accepts SoccerPlayer as an argument.
A few questions:
When I do casting while reading an object.... why I have to use B o_b = (B) one; and why not A o_b = (A) one? Object type is A which I have saved in a file. Also, I want to confirm that when we make an object
like this A a = new B() what is object type in this line?
Moreover, why doesn't the class get saved using an object ?
Why it's not preferable to make static variables to be saved (serializable)?
Code:
import java.io.*;
class A {
public void go(int height){
}
}
public class B extends A implements Serializable{
int height;
public void go(int height){
this.height = height;
System.out.println("height is" + height);
}
public static void main(String[] args){
A a = new B();
a.go(43);
//Saving Object
try{
FileOutputStream f = new FileOutputStream("foo.ser");
ObjectOutputStream o = new ObjectOutputStream(f);
o.writeObject(a);
o.close();
// Reading an Object
FileInputStream filestream = new FileInputStream("foo.ser");
ObjectInputStream p = new ObjectIntputStream(filestream);
Object one = p.readObject();
//Casting
B o_b = (B) one;
p.close();
System.out.println("saved values were" + o_b.height);
} catch (Exception ex){
ex.printStackTrace();
}
}
}
Lets look at what's the type at A a = new B() first. The static type of the variable a is A while the dynamic type is B. So while you use a as if it was of type A in your code it points to an object of type B at runtime. You might want to read up on polymorphism. This also explains why you can cast your deserialized object to B although you serialized a. The object that was acctually serialized was of type B. You could change your initialization of a to A a = new A() and the cast would fail at runtime. Also you should already be getting a compiler warning for an unchecked cast, which basically means it cannot be ensured that the cast suceeds at runtime.
You could also serialize so called class objects. With Class<A> classA = A.getClass() you would have get the class object for class A and would be able to serialize it.
You are serializing instances. A static variable is not part of an instances, it belongs to the class the instances where created from. I think you could serialize static variables by serializing the class object (see 2.) but I'm not sure about that.
I hope this answers your questions. Keep in mind that not everything that can be done should be done. I would consider serializing a class object bad design. There is certainly a better way to persist the content of static variables.
If I instantiate an object in a main class, say:
SomeObject aRef = new SomeObject();
Then I instantiate another object from the main class, say:
AnotherObject xRef = new AnotherObject();
How can the instance of AnotherObject make use of the aRef reference to access the methods in SomeObject? (To use the same instance of SomeObject)
Why not instantiate AnotherObject with a reference to the original SomeObject ?
e.g.
SomeObject obj = new SomeObject();
AnotherObject obj2 = new AnotherObject(obj);
and AnotherObject would look like:
// final used to avoid misreferencing variables and enforcing immutability
private final SomeObject obj;
public AnotherObject(final SomeObject obj) {
this.obj = obj;
}
so AnotherObject has a reference to the previously created SomeObject. It can then use this reference to call methods on. If the original object is not required outside the scope of AnotherObject, then create it inside AnotherObject and enforce encapsulation that way.
I think what you are asking is a question about scope. You're asking how can xRef use aRef during execution? The answer is that the aRef reference needs to be passed into the xRef object when it's being instantiated
xRef = new AnotherObject(aRef)
or after the instantiation you could have
xRef.setSomeObject(aRef)
The answer to his question is making the first class a static class.
xRef.SetSomeObject(aRef);
where SetSomeObject has a signature like
public void SetSomeObject(SomeObject obj)
{
obj.DoStuff();
}
and is a member function of the type AnotherObject.
The strategy design pattern and Decorator design pattern are 2 different ways you can do this.
For instance you can have:
class AnotherObject
{
private SomeObject mySomeObject;
public AnotherObject(SomeObject mySomeObject)
{
this.mySomeObject = mySomeObject;
}
function doSomethingUsingStrategy()
{
mySomeObject.doItTheMySomeObjectWay();
}
function setMySomeObject(SomeObject mySomeObject)
{
this.mySomeObject = mySomeObject;
}
}
Then later on, you can use a different strategy:
myAnotherObject.setMySomeObject(new ExtendsSomeObject);
myAnotherObject.doSomethingUsingStrategy()
You need to provide the reference to aRef to instances of AnotherObject either in the constructor: AnotherObject xRef = new AnotherObject(aRef) or using setter methods: xRex.setSomeObject(aRef). In this case AnotherObject needs to have an instance variable to store aRef that can be used internally like:
class AnotherObject {
SomeObject aRef;
public AnotherObject(SomeObject aRef) {
this.aRef = aRef;
}
public void doSomethingWithSomeObject() {
aRef.doSomething();
}
}
You could also pass instances of SomeObject to methods on AnotherObject that require them like xRef.doSomethingWithSomeObject(aRef).
class AnotherObject {
public void doSomethingWithSomeObject(SomeObject aRef) {
aRef.doSomething();
}
}
There are a bunch of ways to do it (as pointed out by others). You really want to think about your object structure though...
Perhaps your main method shouldn't even be instantiating aRef, perhaps it should be instantiated inside xRef's constructor (this is the case where xRef tends to be a "part" of the functionality of aRef.
If aRef can have multiple instances at some point you may not want to store it off at all, you may want to pass it in whenever an xRef method uses it.
This is where you need to consider your object model at a business logic level. What are the relationships between the objects, etc.
(My guess is that you want xRef to instantiate aRef and keep the reference itself, then if your "main" really needed to talk with aRef it could either ask xRef to forward the message or ask xRef for it's instance of aRef.)
You have to pass the ref and then do something with it.
class AnotherObject {
SomeObject someObject;
public void setSomeObject( SomeObject some ) {
this.someObject = some;
}
public void doSomethingWithSomeObject() {
this.someObject.someMethod();
}
..... rest of your code
}
That way you can use it like this in the main method
public static void main( String [] args ) {
SomeObject xRef = new SomeObject();
AnotherObject aRef = new AnotherObject();
// pass the ref...
aRef.setSomeObject( xRef );
// use it
aRef.doSomethingWithSomeObject();
}
Is that what you need?
Could AnotherObject have a member or property that has a type of SomeObject? That would be another way to handle this too.
So, if there was a "SomeObjectMember" member of the AnotherObject class:
xRef.SomeObjectMember = aRef;