Java. Creating new class similar to List - java

I would like to create my own class, which had 3 fields. The first field - integer, the second would take objects (Strings, Lists), and the third would take integers. I do not understand two things.
How to organize the storage of variables. I need to write a method in which the Array or List will save these values​​? How to save in object values?
For second field. If the input is a String or a List so what Type is needed? and if I want to take as primitive types, then what? How to save object?
public class Record {
private int[] number;
private int[] count;
private Object[] code;
public void add(int newNumber, List<String> newCode, int newCount){
return;
};
public void add(List<String> newCode, int newCount,){
return;
};
This doesn't work.
Object nobj = new Object();
nobj = "ss";

Okay. It appears to me that you've misunderstood the purpose of your class. You've written a class to simulate a single Record, but you've written Record to store many values.
Let's re-arrange your class structure a little
public class Record {
private int number;
private int count;
private Object code;
public Record(int number, int count, Object code)
{
this.number = number;
this.count = count;
this.code = code;
}
Then you can create a class, to manage the interface between the Record class, so for example:
public class Storage
{
List<Record> records;
public Storage()
{
this.records = new ArrayList<Record();
}
public void addRecord(int number, int count, Object code)
{
records.add(new Record(number, count, code));
}
}
That way, you're not messing about with lots of different arrays, which are horrible to try to keep track of, Everything is neatly wrapped up inside your objects.
Your issue with the second attribute
Now, it seems you want to store anything in this variable. This is somewhat more complex than your original problem, but I think that Generics will answer your problem for you. I won't write the code for you, but what I can do is give you a demonstration.
public class GenericExample<T>
{
T object;
public GenericExample(T object)
{
this.object = object;
}
}
Okay, so what I've done here is simple. I've created a new class, GenericExample, and I've said that this class has a special type, T. This type is defined at run time, and means you can define plenty of different values. For example.
GenericExample<String> example = new GenericExample<String>("This is a string");
GenericExample<Object> example2 = new GenericExample<Object>(new Object());
See how you can define the type, and pass it in at run time? Now think about applying it to your class structure.

If you really do not need to create your own List, avoid that. Just create your own type of data and use it as a parameter for List:
public class Record {
private int number;
private int count;
private Object code;
// Constructors, setters and getters
};
List<Record> myList = new ArrayList<>();

Related

Accesing field's methods in composition

I have a class Player which contains few private fields of other classes ( I believe it is called composition ).
public class Player
{
private String name;
private Statistics statistics;
private Experience experience;
private Effort effort;
}
I will post only one of them called Statistics
public final class Statistics
{
Pool pool;
Edge edge;
class Pool
{
private Map<Stats, LimitedInt> map = new HashMap<>();
private int freePoints = 0;
void setAvailable(Stats stat, int value){}
int getAvailable(Stats stat){ return 0; }
void setMax(Stats stat, int value){}
int getMax(Stats stat, int value){ return 0; }
void setFreePoints(int value){}
int getFreePoints(){ return 0; }
void spendFreePoints(Stats stat, int amount){}
}
class Edge
{
private Map<Stats, Integer> map = new HashMap<>();
private int freePoints = 0;
void setMax(Stats stat, int value){}
int getMax(Stats stat, int value){ return 0; }
void setFreePoints(int value){}
int getFreePoints(){ return 0; }
void spendFreePoints(Stats stat, int amount){}
}
}
It is not implemented yet of course, but I want to know what is a correct version of changing for example Player's Pool. I can imagine following scenarios:
Player has exactly the same methods as Pool class which are something like
public class Player
{
// something above
void setAvailablePool(Stats stat, int value){ statistics.pool.setAvailable(stat, value); }
}
This solution seems to be ok but then in Player class I would have a lot of 1-line methods which would just redirect orders to composed fields.
I could transfer pool and edge to the Player class and make them public final but I read that mutable objects should be rather private.
Those 2 are my first thoughts, but I wanted to ask generally how to create interface in class when we use composition.
One-line methods are not a problem, but what makes your solution #1 unsatisfying is the violation of the Law of Demeter (statistics.pool.setXXXX). It might be better to have a statistics.setAvailableInPool() method (or to use your idea #2). I can' t offer more help with the specific implementation because It's not very clear what your Pool and Edge classes are supposed to do (or why they're so similar to each other but do not implement a common interface).
In answer to your general question about creating interfaces for composition, take a look at the SOLID principles. Basically, you should think about what behaviors you need from your dependencies, name those behaviors clearly, and depend on the interface rather than the concrete class. That makes the code easier to understand and easier to change in one place without having to change it everywhere.

Determine which subclass to choose by accessing static variables from the Class object

I am trying to implement an interface in Java to use different types of databases for one application.
My though was to create an abstract class with the common interface and two static variables which are then overwritten by the subclasses. I then wanted to add a Class[] List with the classes of all available subclasses to the abstract class as well as a couple of functions that allow the determination of the correct class to be used.
The goal is to first get a list of all available database types and let the user choose one. Afterwards another function should translate the name (which could be localized) to the IDENTIFIER which is specified in the subclass. Finally a third function allows the instantiation of an object by giving such an IDENTIFIER.
My abstract class would look something like this:
public abstract class DataBase {
public static final IDENTIFIER = "";
public static final NAME = "";
private static final Class[] dbTypes = new Class[]{PostgreSQL.class, MySQL.class};
public static String[] getNameList() {
String[] names = new String[dbTypes.length];
for(int i = 0; i < dbTypes.length; i++){
names[i] = dbTypes[i].NAME; //Cannot access the static variable this way.
}
return names;
}
public static String getIdentifierForName(String name) {
for(int i = 0; i < dbTypes.length; i++){
if(name.equals(dbTypes[i].NAME){
return dbTypes[i].IDENTIFIER;
}
}
return "";
}
public static DataBase getInstanceOf(String identifier) {
for(int i = 0; i < dbTypes.length; i++){
if(identifier.equals(dbTypes[i].IDENTIFIER) {
return dbTypes[i].newInstance();
}
}
return null;
}
}
The Child classes would look something like this:
public class MySQL extends DataBase {
public static final IDENTIFIER = "ab.cde.MySQL";
public static final NAME = "MySQL";
...
}
public class PostgreSQL extends DataBase{
public static final IDENTIFIER = "ab.cde.PostgreSQL";
public static final NAME = "PostgreSQL";
...
}
My problem now is, that I cannot access the static variables from the Class object. Obviously the dbTypes list does not contain any typed classes. I tried changing the type of the Array to Class<? extends DataBase>, but I get an error Cannot create a generic array of Class<? extends DataBase> I also tried checking the classes with isAssignableFrom() and then casting the class, but I was still not able to access the static variables.
For now I have two solutions which are working:
Hardcode all existing subclasses into each function if(PostgreSQL.NAME.equals(name)){...}etc.
However, if I add new subclasses, I only want to have to add them at one point in my implementation.
Instead of using a Class[] array, I can use an array of DataBase[] with instances of each class. However, I would think this is bad practice to instantiate each available DataBase subclass, even though I only need one in the end.
Since I have never done such a thing before I might also be approaching the problem completely wrong. Maybe I am missing the correct way in which something like this is usually done?
Thank you for your help.
There are no "abstract properties" in Java. You have to create two astract methods in the DataBase class, like this:
public abstract class DataBase {
// No "abstract propeties"
public abstract String getDBName();
public abstract String getDBIdentifier();
// etc etc...
}
and then, in each subclass:
public class MySQL extends DataBase {
public static final IDENTIFIER = "ab.cde.MySQL";
public static final NAME = "MySQL";
#Override
public String getDBName() {
return NAME;
}
#Override
public String getDBIdentifier() {
return IDENTIFIER;
}
// etc etc...
}
When using the classes, you can just cast to DataBase (not MySQL or PostgreSQL) and call the two abstract methods.
Therefore, in order to solve your "pick a database class" problem, I would create a configuration file that contains the names of the databases and the corresponding class, and instantiate it with reflection (newInstance()) as needed.
As an alternative, you can use reflection to access the static variables like Nikita's answers suggested, or you can just use the name of the class as the identifier of the database it supports, like this (not tested):
public abstract class DataBase {
private static final Class[] dbTypes = new Class[]{PostgreSQL.class, MySQL.class};
public static Class getDBClass(String type) {
for (Class c : dbTypes) {
if (c.getSimpleName().toLowerCase().equals(type.toLowerCase())) {
return c;
}
}
return null;
}
public static Set<String> getSupportedDB() { // <-- you populate a dropdown menu with this
Set<String> supported = new HashSet<String>();
for (Class c : dbTypes) {
supported.add(c.getSimpleName());
}
return supported;
}
// etc etc...
}
However, I don't like this solution and I would not use it.
You can use reflection to get values for each class:
public static String[] getNameList(){
String[] names = new String[dbTypes.length];
for(int i=0; i<dbTypes.length; i++){
Field f = dbTypes[i].getField("NAME");
names[i] = f.get(null);
}
return names;
}
But it might be slow.
Also I'd suggest to create separate enum DBRegistry that will contain names, identifiers and classes:
public enum DBRegistry {
MYSQL("ab.cde.MySQL", "MySQL", MySQL.class),
POSTGRESQL("ab.cde.PostgreSQL", "PostgreSQL", PostgreSQL.class);
private String name;
private String identifier;
private Class<?> dbClass;
private DBRegistry(String identifier, String name, Class<?> dbClass) {
this.identifier = identifier;
this.name = name;
this.dbClass = dbClass;
}
// Getters...
}
You can iterate on all items in registry using DBRegistry.values
Not tested, but I would suggest something like this. You could register databases by calling DataBase.registerDataBase(new DataBase(...))); which may be invoked from the main file.
public class DataBase {
private final static List<DataBase> INSTANCES = new ArrayList<DataBase>();
private final String identifier;
private final String name;
private final Class<?> dbType;
public DataBase(String identifier, String name, Class<?> dbType) {
this.identifier=identifier.toString();
this.name=name.toString();
this.dbType=dbType;
}
String getIdentifier() {return identifier;}
String getName() {return identifier;}
Class<?> getDbType() {return dbtype;}
public synchronized static void registerDatabase(DataBase database) {
database.getClass();
INSTANCES.add(database);
//may check if already registered and either fail or replace it
}
public synchronized static List<DataBase> getNameList() {
return new ArrayList<DataBase>(INSTANCES);
}
public synchronized static List<String> getNameList() {
List<String> names = new ArrayList<String>(INSTANCES.size());
for (Database db:INSTANCES) names.add(db.getName());
return names;
}
public synchronized static String getIdentifierForName(String name) {
for(DataBase db:INSTANCES){
if(name.equals(db.getName())) return db;
}
return null;
}
public synchronized static DataBase getInstanceOf(String identifier) {
for(DataBase db:INSTANCES){
if(identifier.equals(db.getIdentifier())) return db;
}
return null;
}
}
}
I would advise to keep it simple, never more than necessary to utilize in the actual application. It is easier to extend things than to re-factor code to accomodate for additional complexity. Most of the stuff you mention are merely artefacts of your problem solving, not the actual requirements of your application per se. And it so happens, that a modern object-oriented language has everything you need, and you can implement a good design without reflection and without resorting to static properties and string identifiers.
Remember to rely on the compiler rather than runtime for whatever you know in advance - anything that is known not to change from one application run to another, does not need reflection, because it does not involve runtime variables! I would go for interfaces, classes implementing them, and more importantly the Factory pattern to abstract using these classes:
interface Database
{
void query(String sqlString);
}
class MySQLDatabase implements Database
{
public void query(String sqlString)
{
}
}
class PostgreSQLDatabase implements Database
{
public void query(String sqlString)
{
}
}
class DatabaseFactory
{
Database connectDatabase()
{
/// F.e. return new MySQLDatabase();
}
}
The whole "database abstraction layer" has been done to death already anyway, giving birth to DBA, ODBC and other software stacks that solve your problem. You should let yourself be inspired by these, unless you are sure your particular way of solving this yields advantages that can be proven. If you want to go about this in a professional way, of course. If you want to educate yourself, by all means, use reflection, strings in place of more specific objects, and tight-coupling instead of aggressive modularity.

Let a constructor access a static variable

Right now I have two .java files.
The Main.java:
public class Main {
static int integer = 15;
NeedInteger need = new NeedInteger();
}
and the NeedInteger.java
public class NeedInteger {
System.out.println(integer);
}
This is of course very simplified, but is there any way I can accomplish this?
As many have answered, the correct method is to pass the value in to the constructor of the new class.
If for some reason you cannot do that, then you can use a public static accessor method in Main to access the value (this would be slightly better than just making the field public).
E.g.
public class Main
{
private static int integer = 15;
public static int getInteger()
{
return integer;
}
}
public class NeedInteger
{
public NeedInteger()
{
int integer = Main.getInteger();
}
}
Add a constructor to NeedInteger (and optionally a member if you need to also store it):
public class NeedInteger {
private int integer;
public NeedInteger(int integer) {
this.integer = integer;
System.out.println(integer);
}
}
Then pass your value when you create the instance:
public class Main {
static int integer = 15;
NeedInteger need = new NeedInteger(integer);
}
You would have to do some bad juju moves (like using a global variable) or pass it to the constructor.
NOTE: your
public class NeedInteger {
System.out.println(integer);
}
has no method in it. I would recommend all this to be rewritten as such:
public Class NeedInteger {
NeedInteger(int integer) {
System.out.println(integer);
}
}
If you really want the work to be done on construction.
EDIT: From your comment above.
Instead, have the class structured so:
public Class NeedStringArray {
NeedStringArray(String[][][] stringArr) {
//work with String array here
}
}
That has no real additional overhead, since the actual array will not be passed, but only a reference to it. You WILL likely want to set the array to be final or something, to avoid it being edited in the NeedStringArray constructors.
integer is private, so it cannot be accessed by NeedInteger. you'll have to make it public or use a setter or getter and you'll need to use Main.integer since it's static.
Generally, you set in the Constructor.
Pass in the variable to the class constructor.
An array reference would be just that--a reference.
Or you could pass in the class itself, or use a static (meh).
Per your comment I'd say you can either host your array in a singleton
or as others suggested have the second class accept the reference to the array in the constructor. You can then use Dependency Injection framework (e.g. Guice) to get wire them up

ID generator for the Objects created

I need a class which creates Objects assigning an ID to each Object created. This ID is as usual an int attribute to the class. I want this value (ID) to be increased each time an Object is created and then to be assigned to that Object starting with 1. It strikes me that I need a static int attribute.
How can I initialize this static attribute?
Should I create a separate method to do the increment of the ID (as an ID generator) which is invoked inside the constructor?
What is in general the most effective and well-designed manner to implement that?
You could also try java.util.concurrent.AtomicInteger, which generates IDs in
a atomic way and
sequential
You may use this in a static context like:
private static final AtomicInteger sequence = new AtomicInteger();
private SequenceGenerator() {}
public static int next() {
return sequence.incrementAndGet();
}
Just like you mention use a static int for the id, and increment it when creating new objects.
class MyObject {
private static int counter = 0;
public final int objectId;
MyObject() {
this.objectId = counter++;
}
}
Please note that you need to protect counter++ if MyObject is created by multiple threads (for example using AtomicInteger as the other answers suggest).
I would suggest to use AtomicInteger, which is thread-safe
class MyObject
{
private static AtomicInteger uniqueId=new AtomicInteger();
private int id;
MyObject()
{
id=uniqueId.getAndIncrement();
}
}

How to use names to access variables in Java?

I am trying to write a method in a class which could be invoked several times, each time modifying one of the class' fields. However, I need to new the object and set the field's value to it if I want to modify it, but if do this inside the method, the reference seem to be lost and the field left unchanged after the calling.
Public class A {
private Immutable a; //Immutable class
private Immutable b;
public void modify(Immutable k,int v) {
k=new Immutable(v); //Now I am trying to pass
//a and b as parameters but they remain unchanged
}
}
Is there any way to pass the name of the field into the method (e.g., change the method modify(Immutable k, int v) to modify(String kName, int v), then use the name of the field to access it?
Thanks for any inputs!
Java does not support Call-by-name or call-by-reference, only Call-by-value. Your k variable (the method parameter) is completely independent from any variable used outside of the class (if there was one at all).
You could use Reflection to support passing "a" or "b" (or a Field object), but you should not.
Better have two methods:
public void setA(int v) {
this.a = new Immutable(v);
}
public void setB(int v) {
this.b = new Immutable(v);
}
If it is more complicated than a single constructor call, factor the common part out to a common method.
If you need to access a variable by a String key, you should use a Map.
Map<String, Immutable> _vars = new HashMap<String, Immutable>();
public void modify(String key, int v) {
_vars.put(key, new Immutable(v);
}
What I understand is that you're trying to create a new Immutable given an integer (v). In your modify method right now, k is a temporary reference. Setting the value "k =" in here, only affects the reference stored here in this method, not whatever reference you called modify with.
You have client code like this currently:
A a = new A();
Immutable k = new Immutable(x);
a.modify(k, y);
and you're hoping that k will be changed. What you really want instead of the 3rd line is:
k = new Immutable(y);
Assuming that things are really more complicated, then I would need more information to help you further.
Use a value holder.
public class ValueHolder<T> {
private T value ;
public ValueHolder(T value) {
this.value = value ;
}
public T get() {
return value ;
}
public void set(T value) {
this.value = value;
}
public static <V> ValueHolder<V> make(V value) {
return new ValueHolder<V>(value);
}
}
public class Processor {
private Inmutable a ;
private Inmutable b ;
public void modify(ValueHolder<Inmutable> k, int v) {
k.set(new Inmutable(v));
}
}
Once that is done you can get the instance you just created from the value holder.
Processor processor = new Processor();
ValueHolder<Inmutable> holder = ValueHolder.make(k);
processor.modify(holder, value);
k = holder.get() ;

Categories