#How to get subclass from class name as String? (Class.forName not working)

33 messages · Page 1 of 1 (latest)

north helm
#

hello, I'm a beginner in Java and I use IntelliJ, and I'm looking to replace Class.forName() with something that uses more basic coding. My project structure is I created class Alpha, which contains only 1 variable (public static ArrayList<Beta>). Beta is another class I created, and it extends class Alpha. Beta contains many variables, the class type of one of them is something I created, let's call it Gamma. I also created a bunch of classes that extend Gamma, let's call one of them Delta. So Delta extends Gamma, which extends Beta, which extends Alpha. In the Alpha class, I have a public static method. Inside that method, I use scanner.next() to read a text file and save a letter to variable name, type String. Basically, that letter should refer to one of my Delta classes. So I used Class.forName(name) to fetch me the Delta class that has the same name as the letter (all my Delta classes have just 1 letter in the class name, each with different letter, so all my Delta subclasses are found under Gamma). Problem is this causes ClassNotFoundException. Can anyone please tell me how to fix it or what would be a simpler alternative to fetch a class with a String?

hushed knollBOT
#

This post has been reserved for your question.

Hey @north helm! Please use /close or the Close Post button above when your problem is solved. Please remember to follow the help guidelines. This post will be automatically closed after 300 minutes of inactivity.

TIP: Narrow down your issue to simple and precise questions to maximize the chance that others will reply in here.

visual hemlock
#

Use a Map<String, Class<?>> as a lookup table

#

Initialize it statically or in a constructor

trim saffron
visual hemlock
#

Then all you do is get the class for a string, or throw an error

north helm
visual hemlock
#

No, just Google how to use a Java map

#

Gamma g = (Gamma) map.get(name);

north helm
# visual hemlock Gamma g = (Gamma) map.get(name);

Ok, I initialized the map, but I don't understand why all the elements got saved as a Delta class that isn't even on the map lol I believe the scanner works properly because I have the right number of elements (using my test file), but they all got saved as Z which I added to the ArrayList once before the while loop, so only the 1st element should be Z. The capital letters are the Delta classes. I have below in my Alpha class.

public static ArrayList<Beta> listBeta = new ArrayList<>();
public static Map<String,Gamma> map = new HashMap<>()
{
    {
        Gamma c = new C();
        Gamma d = new D();
        Gamma e = new E();
        Gamma n = new N();
        put("C",c);
        put("D",d);
        put("E",e);
        put("N",n);
    }
};

public static ArrayList<Boolean> method (String filename) {

    ArrayList<Boolean> result = new ArrayList<>();
    listBeta.add(new Z());

    Scanner scanner = null;

    try {
        File file = new File(filename);
        scanner = new Scanner(file);

        while (scanner.hasNext()) {
            String s = scanner.next();
            Gamma type = map.get(s);
            listBeta.add(new Beta(type));

        }
    } catch (FileNotFoundException e) {
        throw new RuntimeException(e);
    } finally {
        scanner.close();
    }

    [... I checked the elements' class types before this part of the code...]
    
    return result;
}
hushed knollBOT
north helm
trim saffron
north helm
north helm
trim saffron
#

Show me the code

#

/run

package a;
public class X {
   public static void main(String[] args) throws ClassNotFoundException {
    String s = "a.Z";
    Class<? extends Y> type = Class.forName(s).asSubclass(Y.class);
    System.out.println(type);
  }
}
class Y extends X {}
class Z extends Y {} 
turbid cargoBOT
#

Here is your java(15.0.2) output @trim saffron

class a.Z
trim saffron
#

Simple example⬆️

north helm
trim saffron
#

Package (if there is one) should be above the imports

turbid cargoBOT
#

Update: Discord changed their client to prevent sending messages
that are preceeded by a slash (/)
To run code you can use "./run" or " /run" until further notice

Here are my supported languages:
awk, bash, basic, basic.net, befunge93, bqn, brachylog, brainfuck, c, c++, cjam, clojure, cobol, coffeescript, cow, crystal, csharp, csharp.net, d, dart, dash, dragon, elixir, emacs, emojicode, erlang, file, forte, forth, fortran, freebasic, fsharp.net, fsi, go, golfscript, groovy, haskell, husk, iverilog, japt, java, javascript, jelly, julia, kotlin, lisp, llvm_ir, lolcode, lua, matl, nasm, nasm64, nim, ocaml, octave, osabie, paradoc, pascal, perl, php, ponylang, powershell, prolog, pure, pyth, python, python2, racket, raku, retina, rockstar, rscript, ruby, rust, samarium, scala, smalltalk, sqlite3, swift, typescript, vlang, vyxal, yeethon, zig

You can run code like this:
./run <language>
command line parameters (optional) - 1 per line
```
your code
```
standard input (optional)

Provided by the Engineer Man Discord Server - visit:
https://emkc.org/run to get it in your own server
https://discord.gg/engineerman for more info

vestal krakenBOT
#

import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Scanner;

public class Alpha {

   public static ArrayList<Beta> listBeta = new ArrayList<>();

   public static ArrayList<Boolean> method (String filename) {

       ArrayList<Boolean> result = new ArrayList<>();
       listBeta.add(new Z());

       Scanner scanner = null;

       try {
           File file = new File(filename);
           scanner = new Scanner(file);

           while (scanner.hasNext()) {
               String s = scanner.next();
               Class<? extends Gamma> type = Class.forName(s).asSubclass(Gamma.class);

               listBeta.add(new Beta(type));

           }
       } catch (FileNotFoundException e) {
           throw new RuntimeException(e);
       } finally {
           scanner.close();
       }

       for (int i = 0; i < listBeta.size(); i++) {
           System.out.println(Gamma.getName(listBeta.get(i)));
       }

       return result;
   }

public class Beta extends Alpha {

   protected Gamma type;
   protected boolean b1;
   protected boolean b2;

   public Beta() {
       this.b1 = false;
       this.b2 = false;
   }
   public <T> Beta (T type) {
       this.type = (Gamma) type;
       this.b1 = false;
       this.b2 = false;
   }

}

public class Gamma extends Beta {

   static String name;

   public Gamma() {
       this.b1 = false;
       this.b2 = false;
   }

   public static String getName(Beta beta) {
       return name;
   }
}

public class Z extends Gamma {

   public Z() {
       this.name = "Zero";
       this.b1 = false;
       this.b2 = false;
   }

}

public class C extends Gamma {

   public C() {
       this.name = "Cookie";
   }
} ```

This message has been formatted automatically. You can disable this using /preferences.

north helm
#

the rest of the Delta classes are pretty much as empty as C

trim saffron
#

What is the output?

#

If it is ClassNotFoundException then the string coming in from the file is incorrect

north helm
# trim saffron What is the output?

At this moment, the method should return an empty ArrayList<Boolean> but it does print to the console the list of names for each of the elements. The test file that I use is just a raw text file, the content looks like this: C E N D E

trim saffron
#

If it does print then what is the issue?

north helm
#

Ok, I think I figured out a simpler way to do this, but now I have a different problem lol so I will close this and open new post. Thank you everyone!

hushed knollBOT