Java: Create a vector of N instances of subclasses - java

I wish to be able to get a List/ArrayList of N new instances from a static method inherited to subclasses so that I don't have to rewrite this same function in all subclasses.
I want to implement this so that I can build a vector containg some A and B. I've tried several methods but none of them worked for me :
public class Parent {
public static List<Parent> getNInstances(int n) {
List<Parent> out = new ArrayList<>();
for (int i = 0; i < n; i++) {
Parent newChildInstance = (Parent) MethodHandles
.lookup()
.lookupClass()
.getConstructor()
.newInstance()
out.add(newChildInstance);
}
}
}
I've got the MethodHandles thing from here since I feel like I need to get the class to be able to call .getConstructor().newInstance() which should, in theory, solve my problem. Nonetheless, this doesn't work, it gives me a NoSuchMethodException since he's not able to find the constructor from the Class given by
MethodHandles.lookup().lookupClass(), at least I think that's why.
Here is how I would like the method .getNInstances() to work.
public class Parent {
public Parent(){ }
public static List<Parent> getNInstances(int n) {
List<Parent> out = new ArrayList<>();
for (int i = 0; i < n; i++) {
Parent newChildInstance = ...
out.add(newChildInstance);
}
}
}
public class A extends Parent {
public A(){ }
}
public class B extends Parent {
public B(){ }
}
public class Main {
public static void main(String[] args) {
List<Parent> total = new ArrayList<>();
total.addAll(A.getNInstances(3));
total.addAll(B.getNInstances(4));
}
}
Here total should therefore be like [a, a, a, b, b, b, b] where a is an instance of A and b an instance of B, but by now, it's just empty.

There's no need at all to use reflection here. Use a factory and a method reference for the constructor.
This way you have compile-time assurance that the constructor you're trying to use actually exists.
abstract class ParentFactory
{
public List<Parent> getNInstances(int n)
{
final List<Parent> out = new ArrayList<>();
for (int i = 0; i < n; i++)
{
out.add(constructor().get());
}
return out;
}
protected abstract Supplier<Parent> constructor();
}
class AFactory extends ParentFactory
{
#Override
protected Supplier<Parent> constructor() {
return A::new;
}
}
class BFactory extends ParentFactory
{
#Override
protected Supplier<Parent> constructor() {
return B::new;
}
}
Sample usage:
List<Parent> total = new ArrayList<>();
total.addAll(new AFactory().getNInstances(3));
total.addAll(new BFactory().getNInstances(4));

I don't manage to reproduce your error.
But note some points :
1) Here, you will never lookup a class of the subclasses because lookupClass() returns the class that invoked the method and this is always Parent.getNInstances() :
Parent newChildInstance = (Parent) MethodHandles
.lookup()
.lookupClass()
.getConstructor()
.newInstance();
Make it an instance method will produce the same result.
2) Generic class should be enough to solve your problem and make it an instance method.
public class Parent<T extends Parent> {
public List<Parent> getNInstances(int n) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
List<Parent> out = new ArrayList<>();
for (int i = 0; i < n; i++) {
Class<T> clazz = (Class<T>) ((ParameterizedType) getClass()
.getGenericSuperclass()).getActualTypeArguments()[0];
Parent newChildInstance =
clazz.getConstructor().newInstance();
out.add(newChildInstance);
}
return out;
}
}
And subclasses :
public class A extends Parent<A> {
//...
}
public class B extends Parent<B> {
//...
}
Sample test :
List<Parent> total = new ArrayList<>();
total.addAll(new A().getNInstances(3));
total.addAll(new B().getNInstances(4));
System.out.println(total);
outputs :
[A#506e6d5e, A#96532d6, A#3796751b, B#67b64c45, B#4411d970,
B#6442b0a6, B#60f82f98]

Related

How to Use a method in super class differently for subclasses ((without enum or any attributes))?

The problem is that I want a super class of A and three subclasses , B,C,D.
and there's a method that only the super class A has , and none of the subclasses have that method and the method has different results in each sub class.
I also can't Override any methods.
how do I code this without using enum or giving any attributes to any class?
for example :
public class {
public String method1(){
//what each class type should do
}
}
public class B extends{
}
public static void main(String[] args) {
A[] elements = {new A(),new B()};
for (int i = 0; i < elements.length; i++) {
System.out.println(elements[i].method1());
}
}
results eg:
A1
B1
Method overriding is the best solution i think.
But if you want to have one function in class A, you can use istanceof to verify the class
if(object instnaceof A) doSomething ..
class A {
public String method1() {
if(this instanceof B) {
return "Class B";
//do something for class B
} else if (this instanceof C) {
return "Class C";
//do something for class C
}
return "";
}
}
class B extends A { }
class C extends A { }
public class Main {
public static void main(String[] args) {
A[] elements = {new A(),new B()};
for (int i = 0; i < elements.length; i++)
System.out.println(elements[i].method1());
}
}
You can use Generics like this, but better use overriding
public class A {
public <T extends A> String method1(T classInstance) {
return method(classInstance);
}
private String method(A classInstance) {
return classInstance.toString();
}
private String method(B classInstance) {
return classInstance.toString();
}
}
public class B extends A{
}
public class Application {
public static void main(String[] args) {
A[] elements = {new A (), new B ()};
for (int i = 0; i < elements.length; i++)
{
System.out.println (elements[i].method1(elements[i]));
}
}
}

Why couldn't I deal with argument in java?

I'm java virgin. I've made really simple code like below.
class TreeData implements Comparable<TreeData> {
private String sixString;
private ArrayList<Integer> stringNum = new ArrayList<Integer>();
private ArrayList<Integer> charNum = new ArrayList<Integer>();
public TreeData(String sixString, int stringNum, int charNum){
this.sixString = sixString;
(this.stringNum).add(stringNum);
(this.charNum).add(charNum);
}
public int compareTo(TreeData other) {
return sixString.compareTo(other.getSixString());
}
public String getSixString(){
return sixString;
}
}
class Child<T extends Comparable<T>>{
public void print(T data){
//error : String a = data.getSixString();
System.out.println("hi");
}
}
public class Test {
public static void main(String[] args) {
Child<TreeData> child = new Child<TreeData>();
TreeData td = new TreeData("sixString", 8, 2);
child.print(td);
}
}
I had a problem in 'print' method in the Child class. When I tried calling the getSixString() method of data(passed as argument), it occurs error. I don't know why I can't using public method in the argument 'data'. Is it related with Generic? Thanks, in advance.
In your Child class, you only define T to be extending Comparable. Yet you expect it to have the method getSixString which Comparable doesn't have. What you probably want it for it to be extending TreeData:
class Child<T extends TreeData>{
public void print(T data){
String a = data.getSixString();
//should work now since T defines getSixString()
}
}
Or better yet if all you want is for T to be TreeData, you don't need any generic class. I'm assuming your real intention was:
class Child extends TreeData {
public void print(){
String a = getSixString();
}
}

covariant return or generic

I want to have a method in an interface that returns a class whose type is not defined in the package. The implementing class will then return a specific type. I can see at least 3 methods how I can do this, shown below as fn1, fn2 and fn3. In all cases there is some form of unchecked cast. Is any of these methods preferred? or is there something better? (assume that the interface I1 and the method dostuff are in some other jar package and do not have access to the Test or the Integer class)
public class Myclass {
public interface I1
{
Object fn1();
<T> T fn2();
<T> T fn3();
}
public class Test implements I1
{
#Override
public Integer fn1() {
return new Integer(1);
}
#Override
public <T> T fn2() {
return (T) new Integer(2); //requires cast to T
}
#Override
public Integer fn3() { //automatic unchecked conversion to T in return value
return new Integer(3);
}
}
public static void main(String[] args) {
Myclass c = new Myclass();
I1 t = c.new Test();
Integer i = (Integer) t.fn1(); //cast required here since I1.fn1() returns Object
Integer j = t.fn2();
Integer k = t.fn3();
dostuff(t);
}
static void dostuff(I1 p)
{
Object i = p.fn1();
Object j = p.fn2();
Object k = p.fn3();
}
}
Can't you use generics with the Interface? Like
public interface I1<T> {
T fn1();
// etc
}
Then there's no casting required when you refer to T.
That's what I prefer, at least. You can then also of course specify what you want T to be using
<T extends myInterface>
I would do it this way
public interface I1<T> {
T fn1();
}
public class Test implements I1<Integer> {
#Override
public Integer fn1() {
return new Integer(1);
}
}
public static void main(String[] args) {
Myclass c = new Myclass();
I1<Integer> t = c.new Test();
Integer i = t.fn1(); <-- no cast
}

get all (derived) interfaces of a class

java.lang.Class.getInterfaces returns all directly implemented interfaces ie doesn't walk the class tree to get all interfaces of all parent types. eg For example the hierarchy
public interface A {}
public interface B {}
public interface C extends B {}
public class Foo implements A {} // Foo.class.getInterfaces() returns [A]
public class Bar implements C {} // Bar.class.getInterfaces() returns [C], note B is not included.
For Bar I would like to get [B, C], but for any arbitrary tree depth.
I could write this myself, but I'm sure a library must exist that does this already, any ideas?
Apache Commons Lang has method you need: ClassUtils.getAllInterfaces
Guava Solution:
final Set<TypeToken> tt = TypeToken.of(cls).getTypes().interfaces();
This is a much more powerful and cleaner reflection API than the ancient Apache stuff.
Don't forget, Spring Framework has many similar util classes like Apache Commons Lang. So there is: org.springframework.util.ClassUtils#getAllInterfaces
public interface A {}
public interface B {}
public interface E extends B{ }
public class C implements A{}
public class D extends C implements E{}
public class App {
public static void main(String[] args) {
final List<Class<?>> result = getAllInterfaces(D.class);
for (Class<?> clazz : result) {
System.out.println(clazz);
}
}
public static List<Class<?>> getAllInterfaces(Class<?> clazz) {
if (clazz == null) {
System.out.println(">>>>>>>>>> Log : null argument ");
return new ArrayList<>();
}
List<Class<?>> interfacesFound = new ArrayList<>();
getAllInterfaces(clazz, interfacesFound);
return interfacesFound;
}
private static void getAllInterfaces(Class<?> clazz,
List<Class<?>> interfacesFound) {
while (clazz != null) {
Class<?>[] interfaces = clazz.getInterfaces();
for (int i = 0; i < interfaces.length; i++) {
if (!interfacesFound.contains(interfaces[i])) {
interfacesFound.add(interfaces[i]);
getAllInterfaces(interfaces[i], interfacesFound);
}
}
clazz = clazz.getSuperclass();
}
}
}

Two questions on inner classes in Java (class A { class B { } })

Sorry for the bad title, but I couldn't think of a better one.
I'm having a class A and a class B which is kind of a sub class of A, like so:
(Is there actually a correct name for it? Isn't "sub class" reserved for inheritance?)
class A {
int i = 0;
class B {
int j = 1;
}
}
class Test {
public static void main() {
A a = new A();
B b = a.new B();
A c = ??? b ??? // get "a" back
}
}
From B every property of A can be accessed, therefore both, a.i and b.i, return 0. Now, I'm wondering whether it's somehow possible to retrieve the original object of type A out of b, as b contains everything that a contains? Simple casting apparently doesn't do the trick.
Second one:
class A {
void print() {
System.out.println("This is class A.");
}
class B {
void print() {
// <--- How to access print() of class A (like this.A.print() or smth)?
System.out.println("This is class B.");
}
}
}
You could alternatively also provide me with some good resources on this topic, as I've been too stupid to find a good one so far.
Thanks in advance. :)
There doesn't seem to be a way to access the outer class from outside. But you can do it like this:
class A {
int i = 0;
class B {
final A outer = A.this;
int j = 1;
}
}
class Test {
public static void main() {
A a = new A();
A.B b = a.new B();
A c = b.outer // get "a" back
}
}
ClassName.this will be the instance of the outerclass associated with the instance of an inner class.
You can access it with the ParentClass.this syntax from within the inner class.
e.g.
public class Outter
{
class Inner {
public Outter getOutter()
{
return Outter.this;
}
}
public Inner getInner(){
return new Inner();
}
}
class Runner{
public static void main(String[] args){
Outter out = new Outter();
Outter.Inner inner = out.getInner();
System.out.println(inner.getOutter().toString());
}
}
[Edit: My answer is appropriate for C# programmers, but I can't guarantee that its applicable to Java.]
B is an inner class, not a subclass of A. Additionally, B does not hold an instance of A, so your code as is cannot return any instance of A.
You need to restructure your classes as follows:
class A
{
public class B
{
public A Parent;
public B(A parent)
{
this.Parent = parent;
}
}
}
Now your B class has a field 'Parent' which returns its parent. You can use these classes as follows (this is C# syntax, because I don't know if Java has a different syntax for instantiating inner classes):
public static void Main(String[] args)
{
A parent = new A();
A.B child = new A.B(child);
A backToParent = child.Parent;
}
Of course, creating your B class in this way seems little funny: technically, you can pass in any parent. It would probably be better to rewrite your A class with a method which returns a B:
class A
{
public class B
{
public A Parent;
public B(A parent)
{
this.Parent = parent;
}
}
public B getChild()
{
return new B(this);
}
}
public static void Main(String[] args)
{
A parent = new A();
A.B child = A.getChild();
A backToParent = child.Parent;
}
this seemed to work for me
class A {
int i = 0;
class B {
int j = 1;
}
}
class Test {
public static void main() {
A a = new A();
A.B b = a.new B();
A c = (A)b.getClass().getDeclaredField("this$0").get(b);
}
}

Categories

Resources