We already have a final class like the following. It has private fields and getters for the fields. It does not have setters but it does have an internal class to set the values for some of the fields. I use Jacksonmapper to construct Vehicle object from a JSON string. After the Vehicle object is constructed, i need to set values for some fields. Since i dont have setters and since i cannot use the ObjBuilder, I used reflection. Instead of using reflection, is there a more proper way to set the values for the private fields, without modifying the Vehicle class?
public final class Vehicle {
private String regNo;
private String make;
private String model;
public String regNo() {
return regNo;
}
public String make() {
return make;
}
public String model() {
return model;
}
public static class ObjBuilder {
Vehicle veh = null;
public ObjBuilder(String regNo) {
veh = new Vehicle(regNo);
}
public ObjBuilder make(String val) {
veh.make = val;
return this;
}
public Vehicle build() {
return veh;
}
}
}
Related
I'm writing an abstract class and have some sub-classes extend it. I have the exact same method with the same implementation in the sub-classes, and I'm wondering if there's a way to avoid the code duplication. The problem is that although the code is completely identical in every class, it uses a static variable of the class. Is there a way to have the method written only once (in the abstract class, for example) and have the method access the static member "NAME" from the class type of the current object?
In other words, is there a way to implement the method getName() only once, and return the NAME static variable of the current type of class?
public abstract class Car {
public abstract String getName();
}
public class Bus extends car{
private static final String NAME = "Bus a Bus A";
public String getName() {
return Bus.NAME;
}
}
public class Taxi extends car{
private static final String NAME = "TAXiiii";
public String getName() {
return Taxi.NAME;
}
}
public class Motor extends car{
private static final String NAME = "motor hehe";
public String getName() {
return Motor.NAME;
}
}
Why not simply pass the name to the super constructor? Although this removes the need for Car to be abstract, because you can simply return the name from its getName method instead.
public class Car {
private final String name;
public Car(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
public class Bus extends Car {
private static final String NAME = "Bus a Bus A";
public Bus() {
super(NAME);
}
}
public class Taxi extends Car {
private static final String NAME = "TAXiiii";
public Taxi() {
super(NAME);
}
}
public class Motor extends Car {
private static final String NAME = "motor hehe";
public Motor() {
super(NAME);
}
}
I want to parse a YAML-file via Jackson but encounter the problem that one of the properties (let's call it 'Event') has a string called 'type' and a 'properties' object that differs for different Events. My issue is that I need to define the POJOs for this YAML. Therefore, I want to define a Hashmap with VariableObject that can be any of some predefined classes (for brevity, let's say Shipping and Inventory).
How can I implement a Hashmap like that?
public class Event {
private static String type;
private static Map<String, VariableObject> properties;
public static void main(String[] args) {
Inventory inventory = new Inventory("inventoryName", 13);
properties.put("Inventory", inventory);
Shipping shipping = new Shipping("shippingName", true);
properties.put("Shipping", shipping);
}
}
public class Inventory {
private static String name;
private static int someNumber;
public Inventory(String name, int someNumber) {
this.name = name;
this.someNumber = someNumber;
}
}
public class Shipping {
private static String name;
private static boolean someBoolean;
public Shipping(String name, boolean someBoolean) {
this.name = name;
this.someBoolean = someBoolean;
}
}
What you're talking ablut is simple Object. It's the most specific common superclass:
private static Map<String, Object> properties;
Other solution would be to make Inventory and Shipping implement some common interface, for example Named and use it as type parameter in HashMap.
One way to do this is to make Shipping and Inventory implements the same interface (like VariableObject in your cas)
public class Event {
private static String type;
private static Map<String, VariableObject> properties;
public static void main(String[] args) {
Inventory inventory = new Inventory("inventoryName", 13);
properties.put("Inventory", inventory);
Shipping shipping = new Shipping("shippingName", true);
properties.put("Shipping", shipping);
}
}
public interface VariableObject{
//you can define common methods here if you want
}
public class Inventory implements VariableObject{
private static String name;
private static int someNumber;
public Inventory(String name, int someNumber) {
this.name = name;
this.someNumber = someNumber;
}
}
public class Shipping implements VariableObject{
private static String name;
private static boolean someBoolean;
public Shipping(String name, boolean someBoolean) {
this.name = name;
this.someBoolean = someBoolean;
}
}
These are two classes of code that I wrote.. the problem here is I am not sure how to define class fields to represent Grass, fire and water as a Type using static..
Also I am not sure if I had used the super function the right way.. How do I properly call the parent's constructor so that I dont have to re define "knockedOut boolean" and be able to use Fire as the type?
Question could be confusing but I am not sure how to explain it better :( sorry
public abstract class Pokemon {
private String name;
private String type;
private int attack;
private int health;
private boolean knockedOut;
static private String Grass;
static private String Water;
static private String Fire;
public Pokemon (String n, String t, int a, int h) {
name = n;//state
type = t;//state
attack = a;//state
health = h;//state
knockedOut = false;
}
public abstract int takeDamage(Pokemon enemy);
public String toString() {
return "}";
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public int getAttack() {
return attack;
}
public void setAttack(int attack) {
this.attack = attack;
}
public int getHealth() {
return health;
}
public void setHealth(int health) {
this.health = health;
}
public boolean isKnockedOut() {
return knockedOut;
}
public void setKnockedOut(boolean knockedOut) {
this.knockedOut = knockedOut;
}
}
public abstract class Charizard extends Pokemon {
private static String Fire;
private int attackFire;
private int healthFire;
private static String Water;
private static String Grass;
public Charizard(int a, int h) {
super("Charizard", Fire, a, h);
attackFire = a;
healthFire = h;
}
public int takeDamage(Pokemon enemy){
int enemyAttack = enemy.getAttack();
if(enemy.getType().equals(Water)){
enemy.setHealth(enemy.getHealth()-attackFire/2);
healthFire = healthFire-enemy.getAttack()*2;
if(enemy.getHealth()<=0){
enemy.setKnockedOut(true);
}
}
else if(enemy.getType().equals(Fire)){
enemy.setHealth(enemy.getHealth()-attackFire/2);
healthFire = healthFire-enemy.getAttack()*2;
if(enemy.getHealth()<=0){
enemy.setKnockedOut(true);
}
}
else if(enemy.getType().equals(Grass)){
enemy.setHealth(enemy.getHealth()-attackFire/2);
healthFire = healthFire-enemy.getAttack()/2;
if(enemy.getHealth()<=0){
enemy.setKnockedOut(true);
}
if(healthFire <=0){
Charizard.set = true;
}
}
return enemyAttack;
}
}
You want to declare your different types like this:
static public final String GRASS= "Grass";
static public final String WATER = "Water";
static public final String FIRE = "Fire";
(I'm following the established convention here that fields declared static, public, and final should have names in all uppercase letters.)
By declaring these fields public, any other classes (including those that extend Pokemon, such as Charizard) that might need to test the type of a Pokemon can use them. By declaring them final, nobody can change them even though they are public. By giving them initial values, you make them actually useful for distinguishing different types of Pokemon, as well as avoid the inevitable NullPointerException that would happen the first time you executed something like p.getType().equals(Pokemon.FIRE)
As for knockedOut, it looks like you're handling it the right way. The field knockedOut is private in Pokemon but you've provided public getter and setter methods that other classes can (and do) use to access it.
There is nothing wrong with the code, but I don't understand why you have to create a private String name, and then equals that string with the string from method i.e. name = n.
public class Person {
private String name;
public Person (String n) {
name = n;
}
public String getName() {
return name;
}
public boolean sameName(Person other) {
return getName().equals(getName());
}
}
A private variable can't be accessed from outside the class, but only by the methods inside the class so it's safer
I'm facing this task:
I have class A and class B. These two classes are different but almost the same.
I need to somehow merge them into 1 Single array of objects so I will be able to use them later in a list that combines both classes.
Class A:
public class Followers {
private String request_id;
private String number_sender;
private String state;
public String getRequest_id() {
return request_id;
}
public String getNumber_sender() {
return number_sender;
}
public String getState() {
return state;
}
}
Class B:
public class Following {
private String name;
private String state;
private String request_id;
public String getRequest_id() {
return request_id;
}
public String getName() {
return name;
}
public String getState() {
return state;
}
}
I've tried doing this next move:
Object[] obj1 = (Object[]) followers;
Object[] obj2 = (Object[]) followings;
Object[] completeArray = ArrayUtils.addAll(obj1, obj2);
Where followers and followings are both arrays of the corresponding classes. Then in my list adapter I use:
if (values[currentItem] instanceof Followers) { BLA BLA BLA}
else if (values[currentItem] instanceof Following) { BLA BLA BLA}
But I get this exception:
Caused by: java.lang.ArrayStoreException: source[0] of type json.objects.Following cannot be stored in destination array of type json.objects.Followers[]
What will be the best way to merge two arrays of different objects into one array?
Will just implementing the same interface between them do the job and then they will basically be in an array of the interface type?
what other ways do you recommend?
Try this
Object[] completeArray = new Object[0];
completeArray = ArrayUtils.addAll(completeArray, obj1);
completeArray = ArrayUtils.addAll(completeArray, obj2);
If you make both classes implement a common interface you can manipulate arrays/lists of them as if they contains instances of the interface.
public interface Follow {
public String getRequest_id();
public String getState();
}
public class Follower implements Follow {
private String request_id;
private String number_sender;
private String state;
public String getRequest_id() {
return request_id;
}
public String getNumber_sender() {
return number_sender;
}
public String getState() {
return state;
}
}
public class Following implements Follow {
private String name;
private String state;
private String request_id;
public String getRequest_id() {
return request_id;
}
public String getName() {
return name;
}
public String getState() {
return state;
}
}
public void test() {
List<Follow> all = new ArrayList<>();
all.add(new Following());
all.add(new Follower());
for ( Follow f : all ) {
String id = f.getRequest_id();
String state = f.getState();
}
}
Alternatively you could put them in a hierarchy:
public class Entity {
private String request_id;
private String state;
public String getRequest_id() {
return request_id;
}
public String getState() {
return state;
}
}
public class Follower extends Entity {
private String number_sender;
public String getNumber_sender() {
return number_sender;
}
}
public class Following extends Entity {
private String name;
public String getName() {
return name;
}
}
public void test() {
List<Entity> all = new ArrayList<>();
all.add(new Following());
all.add(new Follower());
for ( Entity f : all ) {
String id = f.getRequest_id();
String state = f.getState();
}
}
Or you could make the extra fields into attributes.
enum Attribute {
Follows,
Followed;
}
public static class Entity {
private String request_id;
private String state;
EnumMap<Attribute, String> attributes = new EnumMap<>(Attribute.class);
public String getRequest_id() {
return request_id;
}
public String getState() {
return state;
}
// Factory to make entities.
static Entity make(Attribute attribute, String value) {
Entity e = new Entity();
e.attributes.put(attribute, value);
return e;
}
}
public void test() {
List<Entity> all = new ArrayList<>();
all.add(Entity.make(Attribute.Follows, "Fred"));
all.add(Entity.make(Attribute.Followed, "Gill"));
for (Entity f : all) {
String id = f.getRequest_id();
String state = f.getState();
}
}
There are an infinite number of possibilities.
USE concat
var combined= obj1.concat(obj2); // Merges both arrays
Try this.
private Object[] appendObj(Object[] obj, Object newObj) {
ArrayList<Object> temp = new ArrayList<Object>(Arrays.asList(obj));
temp.add(newObj);
return temp.toArray();
}