Iterate through inherited classes and call their static methods - java

I want to iterate through some classes, that inherit from the same superclass.
They all have the same static method, but how can I call it?
I tried it like this, but that does not work:
public abstract class Tower {
private static int text = 5;
public static int getText() {
return text;
}
}
public class aTower extends Tower {
private static int text = 10;
public static int getText() {
return text;
}
}
public class Main {
public static void main(String [] args) {
LinkedList<Class<?extends Tower>> towers = new LinkedList<>();
towers.add(aTower.class);
for (int i = 0; i < towers.size(); i++) {
towers.get(i).getText(); //Does not work
}
}
}
Context
I want to have a list of classes that inherit from Tower for calling static methods of them, for getting e.g. their texture. Is there any other way to do that?
Edit: The main goal is, that I will have many different Towerclasses in a list, and there should be a menu with every towerclass. To paint the menu, I want to get for example the texture, the name, etc. When you click on the menu entry, then you should get an object of the specific tower and you can build it somewhere. But I do not like the idea of having a list of more or less unused instances, and therefore I thought having a static method is the right solution.

Check out Java Interfaces though as already stated they wouldn't be static methods.
public interface ITower {
public String getText();
}
from this point you define your tower objects that implement ITower and then inside main:
public class Main {
public static void main(String [] args) {
List<ITower> towers = new LinkedList<>();
// create your tower objects and add them to the list
towers.add(new ATower());
towers.add(new BTower());
for (ITower iObj : towers) {
iObj.getText();
}
}
}

By converting your static method to an instance method, and using a static field within each subclass, you can get this to work:
public abstract class Tower {
private static int text = 5;
public int getText() {
return text;
}
}
and
public class aTower extends Tower {
private static int text = 10;
#Override public int getText() {
return text;
}
}
and
public class Main {
public static void main(String [] args) {
LinkedList<aTower> towers = new LinkedList<>();
towers.add(new aTower());
for (int i = 0; i < towers.size(); i++) {
towers.get(i).getText();
}
}
}
In your original main() method, you created a List instance for Class objects. I think you had really intended for this to contain aTower instances. This is important because class Class will not have a getText() method.

Polymorphism doesn't work with static methods. Why do you want getText() to be static?
If you have a no-arg constructor in Tower you can use reflection to create an instance from a class name.
Class<Tower> towerClass = (Class<Tower>) Class.forName(classString);
Tower tower = towerClass.newInstance();
tower.staticMethod();

Related

Is there a different way to write get methods in Java?

I know that we can retrieve a variable's value by simply writing get methods and return var;. However, is there another way to write a get method to return information on the fields instead? If so, how does one access it. For example, if I have a planeNumber and I want to check it against another object's planeNumber, is there a way to use a boolean to check instead of writing public int getPlaneNumber()?
Seems like you are wanting to implement the Comparable interface? https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html
That is it looks like you have an attribute, planeNumber, that you want to use to compare the classes?
Maybe you want something like this
import java.util.Comparator;
import java.util.Objects;
public class Airplane implements Comparable<Airplane> {
private final int planeNumber;
public Airplane(final int planeNumber) {
this.planeNumber = planeNumber;
}
public final int getPlaneNumber() {
return planeNumber;
}
#Override
public int compareTo(final Airplane o) {
return Objects.compare(this, o, Comparator.comparing(Airplane::getPlaneNumber));
}
public static void main(final String... args) {
System.out.println(new Airplane(1).compareTo(new Airplane(2)));
System.out.println(new Airplane(100).compareTo(new Airplane(100)));
System.out.println(new Airplane(1000).compareTo(new Airplane(100)));
}
}
-1
0
1
You could add a method comparing the field values to your class like this (omitting null check in the methods):
class Scratch {
public static void main(String[] args) {
ObjectWithPlaneNumber o1 = new ObjectWithPlaneNumber(42);
ObjectWithPlaneNumber o2 = new ObjectWithPlaneNumber(42);
ObjectWithPlaneNumber o3 = new ObjectWithPlaneNumber(11);
System.out.println(o1.hasSamePlaneNumber(o2));
System.out.println(o1.hasSamePlaneNumber(o3));
}
static class ObjectWithPlaneNumber {
private final int planeNumber;
public ObjectWithPlaneNumber(int planeNumber) {
this.planeNumber = planeNumber;
}
public boolean hasSamePlaneNumber(ObjectWithPlaneNumber other) {
return this.planeNumber == other.planeNumber;
}
}
}

How do I execute the function public method declared inside a class which is in turn inside a private method?

So, I want to execute the sum() of the following block of code:
import java.lang.reflect.Method;
public class LocalOuterClass { // start of outer
private int x = 10;
private Object run() { //start of inner
class LocalInnerClass {
private int y = 20;
public void sum() {
System.out.println(x+y);
}
} //end of inner
LocalInnerClass lc = new LocalInnerClass();
//lc.sum();
return lc;
}
public static void main(String[] args) {
LocalOuterClass Loc = new LocalOuterClass();
Object obj = Loc.run();
System.out.println(obj.getClass());
Method[] methods = obj.getClass().getMethods();
for (Method method : methods) {
String MethodName = method.getName();
System.out.println("Name of the method: "+ MethodName);
}
}
} //end of outer
When I do lc.sum(), the sum() is correctly executed. But when I'm returning an object of the inner class to the main() and try to execute sum(), it gives a compiler error. Doing getClass().getMethods() on the object does print sum() as one of the methods. What should I do to execute the sum() inside main()?
You have to change return type to LocalInnerClass and move LocalInnerClass out of the method:
public class LocalOuterClass {
private int x = 10;
private class LocalInnerClass {
private int y = 20;
public void sum() {
System.out.println(x + y);
}
}
private LocalInnerClass run() {
LocalInnerClass lc = new LocalInnerClass();
//lc.sum();
return lc;
}
public static void main(String[] args) {
LocalOuterClass Loc = new LocalOuterClass();
LocalInnerClass obj = Loc.run();
obj.sum(); // it works!
// ...
}
}
The problem is, that the whole LocalInnerClass is not known to your main-method. It does not help, that it has a public method, if the whole type is unknown. You need to refactor your code in order to change that.
Actually your method run currently returns a value of type Object and you'd need to return a value of type LocalInnerClass, however this is not possible due to type visibility.
There are basically two options you have. One is to move the whole LocalInnerClass to a location that is visible to main (like oleg.cherednik suggested):
class LocalOuterClass {
private int x = 10;
private LocalInnerClass run() { // now we can retun `LocalInnerClass`
return new LocalInnerClass();
}
public static void main(String[] args) {
new LocalOuterClass().run().sum(); // works!
}
private class LocalInnerClass {
private int y = 20;
public void sum() {
System.out.println(x+y);
}
}
}
Another option is to implement/extend a different type that has sum, e.g. like this:
class LocalOuterClass {
private int x = 10;
private Summable run() { //start of inner
class LocalInnerClass implements Summable {
private int y = 20;
public void sum() {
System.out.println(x+y);
}
}
return new LocalInnerClass();
}
public static void main(String[] args) {
new LocalOuterClass().run().sum(); // works as well
}
private interface Summable {
void sum();
}
}
With this interface-option the type LocalInnerClass is still not visible to anyone outside your run-method, however the Summable-interface is and since your LocalInnerClass implements Summable you can return a value of that type.

Can outclass specify inner class with InnerClassNameOuter directly rather than ClassName.InnerClassName

In Inner classes of Thinking In Java,
If you want to make an object of the inner class anywhere except from
within a non-static method of the outer class, you must specify the
type of that object as OuterClassName.InnerClassName, as seen in
main().
But I find use InnerClassName directly still works in main.
public class Parcel2 {
class Contents {
private int i = 42;
public int value() { return i; }
}
class Destination {
private String label;
Destination(String whereTo){
label = whereTo;
}
String readLabel(){ return label; }
}
public Destination to(String s){
return new Destination(s);
}
public static void main(String[] args){
Parcel2 q = new Parcel2();
/* Destionation d = q.to("Borneo"); still works.*/
Parcel2.Destination d = q.to("Borneo");
}
}

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();
}
}

Java initial values?

If I were to do something such as:
public class Game
{
private boolean RUNNING = true;
Game()
{
}
public static void main(String[] args)
{
Game game = new Game();
}
}
At what point in time would RUNNING = true?
edit: for clarity, at what point in the program would running be set to true. ex: Before the constructor, after the constructor, etc.
It will be set to true before the constructor. You can use it in the constructor as true.
This code explains itself:
public class SuperClass
{
String superField = getString("superField");
public SuperClass()
{
System.out.println("SuperClass()");
}
public static String getString(String fieldName)
{
System.out.println(fieldName + " is set");
return "";
}
public static void main(String[] args)
{
new ChildClass();
}
}
class ChildClass extends SuperClass
{
String childField = getString("childField");
public ChildClass()
{
System.out.println("ChildClass()");
}
}
OUTPUT:
superField is set
SuperClass()
childField is set
ChildClass()
When the constructor is called using the new operator all non-static members of the class are initialized before the code inside the constructor is executed. You can use the debugger and step into that call and see where it goes first. Static members are initialized when the class is loaded and for the first time accessed (see this question for more detailed info about static members).
private boolean RUNNING = true;
Game() {
}
is exactly the same as
private boolean RUNNING;
Game() {
RUNNING = true;
}
Actually, the comiler will move the initialization at the beginning of the constructor. The value will then be set when instantiating an object of that class.
When you try to use local variables which not manually initialized, you will get a compile time error.
public static void main(String args[]){
int a;
System.out.pritnln(a); //error
}
But it's not the case with instance variables. This itself shows that they are ready for usage before the constructor even.
public class Example{
private int a;
public Example(){
System.out.println(a); //No error
}
public int getA(){
return a; //No error
}
}
I hope this intuition answers your question..........

Categories

Resources