How do I get the dynamic class name of an object? - java

So I have a List of Actors and I want to get each Actors dynamic class name.
For example here is my Actor list: People, Birds, Cows.
I want to get as result the same: "People, Birds, Cows" but without a name attribute in the Actors class. Is it possible?
Example code (here instead of list I used array) :
public Area map[][];
map[0][0] = new AntHillArea();
String name = map[0][0].getClass().getName(); //this results "Area" instead of AntHillArea
Edit: There was other problems with the code, getClass().getName() works fine. Thanks anyway.

String className = obj.getClass().getSimpleName();
Update:
public class Test {
public static void main(String[] args) {
Area map[][] = new Area[1][1];
map[0][0] = new AntHillArea();
String name = map[0][0].getClass().getSimpleName(); // returns "AntHillArea"
System.out.println(name);
}
}
class Area {
}
class AntHillArea extends Area {
}
Use getSimpleName method. It gives you only class and will remove any package if having.

You can do this:
class Dog
{
//code
public String getName()
{
return Dog.class.getName();
}
//better
#Override
public String toString()
{
return Dog.class.getName();
}
}
And similarly for each class. Or have a global one as mentioned in other answers as:
public static String getClassName(Class<?> clas){
return clas.getName();
}
To use Dog dog = new Dog(); getClassName(dog.class);

Related

How can I assign instance of a class from an array to a class initializer in java?

In a Android application I am making I have an array of instances of a certain class I made, and later in the program I need to use the getter and setter methods from that class on an instance of the class from the array. Do I need to assign the instance of the class from the array to a new class initializer? Here is some code to clear this up:
Class
public class ProfileInformation {
private String console;
private String gamertag;
public String getConsole() {
return console;
}
public void setConsole(String console) {
this.console = console;
}
public String getGamertag() {
return gamertag;
}
public void setGamertag(String gamertag) {
this.gamertag = gamertag;
}
}
Array
ArrayList<ProfileInformation> ProfTags = new ArrayList<>();
Some instances of ProfileInformation are then added to arraylist, and then I get one of the instances from the arraylist and try to use getGamertag() to set it to a string:
ProfileInformation profNew = ProfTags.get(ProfTags.size()-1);
String example = profNew.getGamertag();
The problem is example will equal null. Why is this?
First, an Arraylist is a List, try not to confuse that with actual arrays.
Do I need to assign the instance of the class from the array to a new class initializer?
You don't need to get an element out of the Arraylist, no. You can chain many methods together
String example = ProfTags.get(ProfTags.size()-1).getGamertag();
example will equal null. Why is this?
For the same reason any object is null... You never set it equal to anything else
This code runs on my laptop:
public static void main(String[] args) {
ArrayList<ProfileInformation> ProfTags = new ArrayList<>();
element = new ProfileInformation();
element.setGamertag("Actual Gamer tag value");
ProfTags.add(element);
ProfileInformation profNew = ProfTags.get(ProfTags.size()-1);
String example = profNew.getGamertag();
}
Output is:
Actual Gamer tag value
I guess you didn't call setGamertag(String).

Java: Inmutable static variable, possible?

I have a class with this, it's an example code, not the real code
private static String className;
public static Wish getInstance(Class<?> clazz) {
if(wish == null)
wish = new Wish();
className = clazz.getName();
return wish;
}
Many classes use this Wish class, then each class should "say" a wish with the className passed in the getInstance method.
Then I have something like this
public class Boy {
private Wish w = Wish.getInstance(Boy.class);
//at this moment the static variable take "com.package.Boy" value
....
}
Another classs
public class Girl {
private Wish w = Wish.getInstance(Girl.class);
//at this moment the static variable take "com.package.Girl" value
....
}
When everybody start to say their wishes, example
public class WishesDay {
private Girl g;
private Boy b;
public void makeYourWish() {
g = new Girl(); //get the com.package.Girl value
b = new Boy(); //get the com.package.Boy value
//sample output "com.package.Boy wants A pink house!"
g.iWish("A pink house!"); // the boys don't want this things :(
b.iWish("A spatial boat!");
}
}
I know that each object have the same copy o the Wish class and the static variable className change when each object (Girl, Boy) call the Wish.getInstance(Class<?> clazz) method.
How can I use a static variable (I want avoid to instantiate the Wish class) and keep the correct value for the variable className.
Can I make this with a static variable? or the solution is to instantiate (no static variable)
For example, log4j has the Logger class, I want to make the same thing with the class name.
You'll have to make your constructor private if you want to avoid instantiate the Wish class and make the className not static.
public class Wish {
String className;
private Wish(String className){
this.className = className;
}
public static Wish getInstance(Class<?> clazz) {
String className = clazz.getName();
return new Wish(className);
}
public String getClassName() {
return className;
}
}
package com.test;
public class WishesDay {
private Girl g;
private Boy b;
public void makeYourWish() {
g = new Girl(); //get the com.package.Girl value
b = new Boy(); //get the com.package.Boy value
//sample output "com.package.Boy wants A pink house!"
g.iWish("A pink house!"); // the boys don't want this things :(
b.iWish("A spatial boat!");
}
public static void main(String[] args) {
WishesDay wd = new WishesDay();
wd.makeYourWish();
//outputs com.test.Girl wants A pink house!
//com.test.Boy wants A spatial boat!
}
}

Encapsulation for Reference Variables?

It may be a common question but I couldn't find nice explanation for it. I am trying to understand the encapsulation of reference variables in Java.In the below code:
class Special {
private StringBuilder s = new StringBuilder("bob");
StringBuilder getName() { return s; }
void printName() { System.out.println(s); }
}
public class TestSpecial {
public static void main (String[] args ) {
Special sp = new Special();
StringBuilder s2 = sp.getName();
s2.append("fred");
sp.printName();
}
}
Output: bobfred
At first I thought making our field private and providing a getter method, it's a good encapsulation technique. But when I took closer look on it, I saw that when I invoke getName(), I do in fact return a copy, just like Java always does. But, I am not returning a copy of the StringBuilder object. I am returning a copy of the reference variable that point to the one and only StringBuilder object. So, at the point that getName() returns, I have one StringBuilder object and two reference variables pointing to it ( s and s2).
What are the techniques to make it well encapsulated?? A good explanation with code example expected :) . Thanks in advance.
There are two basic approaches I can think of.
The first is to only return immutable values. The caller can then do what he wants without risking the integrity of your object. In your case, the immutable type would be String:
class Special {
private String s = "bob";
String getName() { return s; }
void printName() { System.out.println(s); }
}
public class TestSpecial {
public static void main (String[] args ) {
Special sp = new Special();
String s2 = sp.getName();
s2 += "fred";
// Alternatively: StringBuilder s2 = new StringBuilder(sp.getName()).append("fred");
sp.printName(); // prints "bob"
}
}
Note: If s needs to be a StringBuilder, you can return s.toString().
The other option is to return a mutable value, but create a defensive copy in your getter. In other words, return a separate reference with duplicate data:
class Special {
private StringBuilder s = new StringBuilder("bob");
StringBuilder getName() { return new StringBuilder(s); } // return a copy of s
void printName() { System.out.println(s); }
}
public class TestSpecial {
public static void main (String[] args ) {
Special sp = new Special();
StringBuilder s2 = sp.getName();
s2.append("fred");
sp.printName(); // prints "bob"
}
}
There can be multiple ways to apply encapsulation to mutable object.
By providing copy constructor (in above example new StringBuilder(oldBuilder.toString())
public class Student{
private String name;
public Student(Student s){
this.name = s.name;
}
}
Using prototype pattern with clone method. But copy Constructor is recommend over clone method.
public Student implements Cloneable{
private int rollNo;
private String name;
public Student clone(){
Student s = (Student)super.clone();
s.name = this.name;
s.rollNo = this.rollNo;
return s;
}
}
public class Clazz{
private Map students= new HashMap();
public student getStudent(int rollNo){
Student s = students.get(rollNo);
return s.clone();
}
}
Using immutable form of mutable object. e.g. Collections.unmodifiablecollection().
Whenever we return collection or array, always return read-only form. So modifications to collection will not impact the state of the object.

How to add to an arraylist of class type

Ok so this is what I have
public class Register {
public String propertyID;
public String PPSNumber;
Register(String aPropertyID, String aPPSNumber) {
propertyID = aPropertyID;
PPSNumber = aPPSNumber;
}
public void setPPSNumber(String aPPSNumber) {
PPSNumber = aPPSNumber;
}
public String getPPSNumber() {
return PPSNumber;
}
public String getPropertyID() {
return propertyID;
}
}
Then I have this
public static ArrayList<Register> registers = new ArrayList<Register>();
public static void main(String[] args) {
String userInput1 = "", userInput2 = "", userInput3 = "";
userInput1 = JOptionPane.showInputDialog("Enter your PPSNumber");
userInput2 = JOptionPane.showInputDialog("Enter your propID");
registers.add("number", "id");
}
I don't understand why It wont let me add to the ArrayList. Is there some way of adding class types to ArrayLists?
Try this instead :
registers.add(new Register("number","id"));
EDIT 1:
To answer your question, you can create a separate "register" and the use the getters :
Register aRegister = new Register("number","id");
registers.add(aRegister);
System.out.println(aRegister.getPropertyID()+" "+ aRegister.getPPSNumber());
Your List is of type Register so you need to add object of Register class only.
Nothing wrong in create as many Register objects as required.
You can implement toString() method inside Register class then the below sysout will work given the register variable is initialized with Register object. Check this How to override toString() properly in Java? to know about toString implementation.
System.out.println(register)

Java-How do I call a class with a string?

I am a beginner programmer and this is my first question on this forum.
I am writing a simple text adventure game using BlueJ as a compiler, and I am on a Mac. The problem I ran into is that I would like to make my code more self automated, but I cannot call a class with a string. The reason I want call the class and not have it all in an if function is so that I may incorporate more methods.
Here is how it will run currently:
public class textadventure {
public method(String room){
if(room==street){street.enterRoom();}
}
}
public class street{
public enterRoom(){
//do stuff and call other methods
}
}
The if statement tests for every class/room I create. What I would like the code to do is automatically make the string room into a class name that can be called. So it may act like so:
Public method(string room){
Class Room = room;
Room.enterRoom();
}
I have already looked into using Class.forName, but all the examples were too general for me to understand how to use the function. Any help would be greatly appreciated, and if there is any other necessary information (such as more example code) I am happy to provide it.
-Sebastien
Here is the full code:
import java.awt.*;
import javax.swing.*;
public class Player extends JApplet{
public String textOnScreen;
public void start(){
room("street1");
}
public void room(String room){
if(room=="street1"){
textOnScreen=street1.enterRoom();
repaint();
}
if(room=="street2"){
textOnScreen=street2.enterRoom();
repaint();
}
}
public void paint(Graphics g){
g.drawString(textOnScreen,5,15);
}
}
public abstract class street1
{
private static String textToScreen;
public static String enterRoom(){
textToScreen = "You are on a street running from North to South.";
return textToScreen;
}
}
public abstract class street2
{
private static String textToScreen;
public static String enterRoom(){
textToScreen = "You are on another street.";
return textToScreen;
}
}
Seeing as you are rather new to programming, I would recommend starting with some programs that are simpler than a full-fledged adventure game. You still haven't fully grasped some of the fundamentals of the Java syntax. Take, for example, the HelloWorld program:
public class HelloWorld {
public static void main(String[] args) {
String output = "Hello World!"
System.out.println(output);
}
}
Notice that public is lowercased. Public with a capital P is not the same as public.
Also notice that the String class has a capital S.* Again, capitalization matters, so string is not the same as String.
In addition, note that I didn't have to use String string = new String("string"). You can use String string = "string". This syntax runs faster and is easier to read.
When testing for string equality, you need to use String.equals instead of ==. This is because a == b checks for object equality (i.e. a and b occupy the same spot in memory) and stringOne.equals(stringTwo) checks to see if stringOne has the same characters in the same order as stringTwo regardless of where they are in memory.
Now, as for your question, I would recommend using either an Enum or a Map to keep track of which object to use.
For example:
public class Tester {
public enum Location {
ROOM_A("Room A", "You are going into Room A"),
ROOM_B("Room B", "You are going into Room B"),
OUTSIDE("Outside", "You are going outside");
private final String name;
private final String actionText;
private Location(String name, String actionText) {
this.name = name;
this.actionText = actionText;
}
public String getActionText() {
return this.actionText;
}
public String getName() {
return this.name;
}
public static Location findByName(String name) {
name = name.toUpperCase().replaceAll("\\s+", "_");
try {
return Enum.valueOf(Location.class, name);
} catch (IllegalArgumentException e) {
return null;
}
}
}
private Location currentLocation;
public void changeLocation(String locationName) {
Location location = Location.findByName(locationName);
if (location == null) {
System.out.println("Unknown room: " + locationName);
} else if (currentLocation != null && currentLocation.equals(location)) {
System.out.println("Already in room " + location.getName());
} else {
System.out.println(location.getActionText());
currentLocation = location;
}
}
public static void main(String[] args) {
Tester tester = new Tester();
tester.changeLocation("room a");
tester.changeLocation("room b");
tester.changeLocation("room c");
tester.changeLocation("room b");
tester.changeLocation("outside");
}
}
*This is the standard way of formating Java code. Class names are PascalCased while variable names are camelCased.
String className=getClassName();//Get class name from user here
String fnName=getMethodName();//Get function name from user here
Class params[] = {};
Object paramsObj[] = {};
Class thisClass = Class.forName(className);// get the Class
Object inst = thisClass.newInstance();// get an instance
// get the method
Method fn = thisClass.getDeclaredMethod(fnName, params);
// call the method
fn.invoke(inst, paramsObj);
The comments below your question are true - your code is very rough.
Anyway, if you have a method like
public void doSomething(String str) {
if (str.equals("whatever")) {
// do something
}
}
Then call it like
doSomething("whatever");
In Java, many classes have attributes, and you can and will often have multiple instances from the same class.
How would you identify which is which by name?
For example
class Room {
List<Monster> monsters = new ArrayList <Monster> ();
public Room (int monstercount) {
for (int i = 0; i < monstercount; ++i)
monsters.add (new Monster ());
}
// ...
}
Monsters can have attributes, and if one of them is dead, you can identify it more easily if you don't handle everything in Strings.

Categories