Instantiate a class inside a function in Java - java

I'm trying to create a function which fills a 2d array with some objects. My function looks like this:
void funcName(Element el){
container[0][0] = new el(args);
}
The only issue here is that Element is an abstract class, and so Java gives me an error when I try to instantiate an object. What I am trying to do is instantiate objects of classes which are built as extension to Element (i.e Class B extends Element). Is there a way to pass those classes as an argument, and have my function create them accordingly?

The abstract class:
public abstract class Element {
public abstract void myMethod();
}
The concrete class:
public class ArrayElement extends Element{
#Override
public void myMethod() {
System.out.println("Hello!");
}
}
The calling must be done in this way:
public class Main {
public static void main(String[] args) {
Element element = new ArrayElement();
calculate(element);
}
// This syntax will let you use any class that extends from the Element class, since it guarantees that is convertible to the type that you need. Are called generics.
public static <T extends Element> void calculate(T element){
element.myMethod();
}
}

Try this.
static abstract class Element {}
static class B extends Element {}
static void funcName(Class<? extends Element> cls)
throws InstantiationException, IllegalAccessException,
IllegalArgumentException, InvocationTargetException,
NoSuchMethodException, SecurityException {
Element[][] container = new Element[1][1];
container[0][0] = cls.getConstructor().newInstance();
and
funcName(B.class);
Or
static void funcName(Supplier<Element> s) {
Element[][] container = new Element[1][1];
container[0][0] = s.get(); // is equivalent to `new B()`
}
and
funcName(B::new);

Related

How to create constructor in java parameterized with class?

I want to have a class to run other classes in java, like constructor parameterized with a class to run that class later on, similar to this
class MyClass{
Class classToRun;
public MyClass(Class c) {
super();
this.classToRun = c;
}
public void runClass(){
classToRun.someStaticMethod();
}
}
where classToRun possible classes doesn't have a common ancestor, but all have method someStaticMethod, and have no idea about MyClass, which runs them.
But there are problems, like inner classes cannot have static methods, classes cannot be cast Class, etc.
There are solutions for parameterized with class methods, like
How do I pass a class as a parameter in Java?
Passing a class as an argument to a method in java
but not for constructors.
What is the proper solution to do this?
Use lambdas and pass the method reference: they match on the method signature. For void someStaticMethod() you can use Runnable.
class MyClass{
private final Runnable methodToRun;
public MyClass(Runnable someStaticMethod) {
methodToRun = someStaticMethod;
}
public void runClass(){
methodToRun.run();
}
}
new MyClass(SomeClass::someStaticMethod).runClass();
You cannot enforce that the method passed has the right name, but looks even neater IMHO.
You need to understand what generics are.
interface
public interface SomeInterface {
void someStaticMethod();
}
use
class MyClass<T extends SomeInterface>{
T classToRun;
public MyClass(T c) {
super();
this.classToRun = c;
}
public void runClass(){
classToRun.someStaticMethod();
}
}
As 2 of 3 answers were not to the point, I decided to publish fixed versions of both answers as far as they can be fixed.
The f1sh version from the above should like follows:
public class ClassToRunOthers {
Class classToRun;
public ClassToRunOthers(Class c) {
this.classToRun = c;
}
public void runClass() throws Exception {
Optional<Method> method = Arrays.stream(classToRun.getDeclaredMethods()).filter(m -> m.getName().equals("someStaticMethod")).findFirst();
if(!method.isPresent()) {
throw new RuntimeException();
}
method.get().invoke(null);
}
public static void main(String[] args) throws Exception {
ClassToRunOthers mc = new ClassToRunOthers(SomeClass.class);
mc.runClass();
}
}
class SomeClass {
static void someStaticMethod() {
System.out.println("test");
}
}
The zwei solution above can not be fixed without reflection, as generics is not to the point. Evan if you try to parametrize not with SomeInerface (because SomeClass does not extend a common SomeInterface), but with Object, it is still won't solve the problem:
public class MyClass<T extends Object> {
T classToRun;
public MyClass(T c) {
super();
this.classToRun = c;
}
public void runClass() {
// classToRun.someStaticMethod(); // Cannot resolve method 'someStaticMethod' in 'T'
}
public static void main(String[] args) {
MyClass mc = new MyClass(SomeClass.class);
}
}
class SomeClass {
static void someStaticMethod() {
System.out.println("test");
}
}
This can be fixed like the above, via reflection.
I believe, it can be done with annotations in some elegant way, and may be someone will share us with such a solution or I will do it by myself as time permits.
By now for myself, a solution with saving class name in the String in constructor next day after the question been asked did the trick.
You will have to use reflection if you want to execute a method when you only have the Class instance.
In the code below, runClass finds the method of the class using it's name as a String, then executes it. This code assumes that the method is static, also ignoring any Exception handling.
The following code prints "test":
class MyClass {
Class classToRun;
public MyClass(Class c) {
this.classToRun = c;
}
public void runClass() throws Exception {
Optional<Method> method = Arrays.stream(classToRun.getDeclaredMethods()).filter(m -> m.getName().equals("someStaticMethod")).findFirst();
if(!method.isPresent()) {
throw new RuntimeException();
}
method.get().invoke(null);
}
}
class Main {
public static void main(String[] args) throws Exception {
MyClass mc = new MyClass(Main.class);
mc.runClass();
}
static void someStaticMethod() {
System.out.println("test");
}
}

Find the Class Reference Of Genric Type

#Service
public abstract class MainService<E extends AbstractEntity, R extends MainRepository<E>> {
#Autowired
MainRepository<E> repository;
public E find(long id) throws Exception {
return this.repository.find(---, id);
}
}
Here is it possible to find the class reference of the generic type E to pass through this method as first argument instead of the --- ...?
My expectation about the implementation is to create a generic call to avoid the repetition of the below code in all service classes.
return this.repository.find(Entity.class,id);
Yes, here's an example of doing that:
import java.lang.reflect.ParameterizedType;
public class Foo {
public static abstract class Bar<E> {
public E returnAnE() throws InstantiationException, IllegalAccessException {
Class e = (Class)((ParameterizedType)this.getClass().getGenericSuperclass()).getActualTypeArguments()[0];
return (E)e.newInstance();
}
}
public static class Baz extends Bar<String> {
}
public static void main(String[] args) throws InstantiationException, IllegalAccessException {
Baz baz = new Baz();
String s = baz.returnAnE();
}
}
This code will fail with class structures which don't match what we have here, so you should do instance of checks instead of casts, and check array accesses.

Confusion with generics, java

I have generic class :
public class Test<T> {
private Test<? extends T> myInstance;
public Test<? extends T> getInstance () {
return myInstance;
}
public void setInstance (Test<? extends T> argType) {
this.myInstance = argType;
}
}
And I have two classes in my class hierarchy relations:
public abstract class Alphabet {
//code here
}
and
public class A extends Alphabet{
public A() {
super();
System.out.print("This is A call");
}
}
Finally I have a class where I want to store make generic class Test with particular type and set new Instance of Object -> A through setInstance() method:
public static void main(String[] args) {
List<Alphabet> list = new ArrayList<Alphabet>();
Test<Alphabet> tAlphabet = new Test<Alphabet>();
tAlphabet.setInstance(new A()); //Here is compilation ERROR
}
But I have got the compilation error in line tAlphabet.setInstance(new A());
What is the issue with my generic class?
Your instance is a Test object as it's currently written, and you are supplying it with an Alphabet object instead. You probably want your instance to be of type Alphabet:
public class Test<T> {
private T myInstance;
public T getInstance() {
return myInstance;
}
public void setInstance(T argType) {
myInstance = argType;
}
}
This way, your Test stores an Alphabet instead of another Test.
It seems you have made things more complicated than needed. You probably want this in your Test class instead of what you actually have:
private T myInstance;
public T getInstance () {
return myInstance;
}
public void setInstance (T argType) {
this.myInstance = argType;
}
With this arrangement you would be free to setInstance(new A()) on a Test<Alphabet> instance.

How to get class object without an instance or class name

I have an abstract class MyClass with a static method to populate given collection with a number of MyClassDescendant objects. This method should call a static getRandom() method of MyClassDescendant to get object instances.
My current code looks like this:
public static void populate(Collection<MyClass> coll, Class<? extends MyClass> cl, int num) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
for (int i = 0; i < num; i++) {
Method m;
m = cl.getMethod("getRandom");
coll.add((MyClass)(m.invoke(null)));
}
}
Then I call it like that:
MyClass.populate((Collection<MyClass>)(Collection<?>)collection, MyClassDescendant.class, 3);
This code works, but it's ugly. What I actually wanted to achieve would look like this:
MyClassDescendant.populate(collection, 3);
If it wasn't a static method, I'd just use this.getClass(). I know that MyClass.class would work for static method, but I don't want class for MyClass, but for specific MyClassDescendant (there are few descendant types).
Is there any way to get class object without having its instance or class name?
Since you are in a static context you'll have to duplicate some code, but you can do delegation.
public class MyClassDescendant extends MyClass {
public static void populate(Collection<MyClass> coll, int count) {
MyClass.populate(coll, MyClassDescendant.class, count);
}
}
Now you can call
MyClassDescendant.populate(collection, 3);
Try restructuring your method in this way:
public static <T extends Base> void populate(Collection<T> coll, int num) throws Exception{
for (T item : coll) {
Method m;
m = item.getClass().getMethod("getRandom");
coll.add((T)(m.invoke(null)));
}
}
With regards to one the comments, you can also use the template method design pattern to utilize inheritance for your getRandom() method by making it abstract and calling it within your populate method.
If get random is a static method couldn't you just call it?
public interface MyClassInterface {
MyClass getRandom();
}
public abstract class MyClass implements MyClassInterface {
public static void populate(Collection<MyClass> coll, int num) {
for (int i = 0; i < num; i++) {
coll.add((MyClass)MyClassDescendant.getRandom());
}
}
}
public class MyClassDescendant extends MyClass {
public MyClass getRandom() {
// implementation of getRandom
}
}

How to infer subtype in supertype

Say you have a super-class. In that super class you want to pass runtime object of itself (this) as a parameter to an overloaded method. Trick is, this overloaded method is overloaded by sub-class type. When you try to do it, you'll get a
method ... is not applicable(actual argument
... cannot be converted to ... by method invocation
conversion)
Instead you would need to implement the method separately in each subtype (just to get the correct runtime class), which is a lot of duplicate effort when the contents of the method are identical.
e.g:
public class InferTypeTest {
public static void main(String[] args) {
SubClass1 s1 = new SubClass1();
s1.sayHi();
}
public static void sayHi(SubClass1 clz) {
System.out.println("clz 1");
}
private abstract static class SuperClass{
public void sayHi() {
InferTypeTest.sayHi(this);
}
}
private static class SubClass1 extends SuperClass{
}
}
Yes, this is how double dispatch works, you have to override the accept method in each subclass like this:
private static abstract class NodeWithChildren implements DomNode {
/* snip */
public void accept(DomNodeVisitor visitor) {
for (DomNode child : children) {
child.accept(visitor);
}
}
}
private static class BodyNode extends NodeWithChildren {
public void accept(DomNodeVisitor visitor) {
visitor.visit(this);
super.accept(visitor);
visitor.visited(this);
}
}
private static class DivNode extends NodeWithChildren {
public void accept(DomNodeVisitor visitor) {
visitor.visit(this);
super.accept(visitor);
visitor.visited(this);
}
}
}
BodyNode is a NodeWithChildren
DivNode is a NodeWithChidren
NodeWithChildren is a DomNode
DomPrinterVisitor is a DomNodeVisitor
DomNodeVisitor's visitor can visit "BodyNode" or "DivNode, But you are passing "NodeWithChildren" to visit.
Here BodyNode is a NodeWithChildren but NodeWithChildren is not BodyNode/
Theary is if B extends A, you can say B is a A/ not A is a B.

Categories