New to Java. I'm trying to create a class to convert to JSON string to send as POST request using GSON. This class was created within a public class Called BertClient:
private class BertJsonRequest {
private Integer id;
private List<String> texts;
public BertJsonRequest(int x, String text) {
this.id = x;
this.texts = new ArrayList<>();
this.texts.add(text);
}
}
How I use that:
BertJsonRequest rawRequestBody = new BertJsonRequest(1, text);
Gson gsonToJson = new Gson();
String requestBody = gsonToJson.toJson(rawRequestBody);
For the line where I'm creating new BertJsonRequest My IDE tells me that BertClient.this cannot be referenced from a static content.
I wonder what that means.
Am I building the constructor correctly?
I think I'm not. I just want to be able to pass in a String so that constructor can create a List of String using that String.
Your class access modifier is set to private. Try setting the access modifier to public instead.
public class BertJsonRequest {
private Integer id;
private List<String> texts = new ArrayList<>();
public BertJsonRequest(int x, String text) {
id = x;
texts.add(text);
}
}
What I understood by reading your comments on other's answers was, that your BertClientRequest probably is an inner class.
In case it really is an inner class, and you try to call it in a static method of your containing class, it becomes apparent that you cannot instantiate your inner class as that inner class is not static.
public class BertClient {
private class BertClientRequest {
/* some code */
}
static void aStaticMethod() {
// ...
// Inner class BertClientRequest is unknown to your static method as it is not static,
// thus giving you a compile time error
BertClientRequest rawRequest = new BertClientRequest(1, text);
// ...
}
}
The fix would be in this case to change your inner class to static:
private static class BertClientRequest
I guess your BertJsonRequest is a inner class of BertClient. You can't instantiate BertJsonRequest outside of BertClient. You can make BertJsonRequest class static for this to work.
Related
Is it not possible to create a list with an inner class with Jackson? The external class Tradables will work perfectly. But the inner class Underlyings will not work (Same of course if I make Tradables an inner class).
Is there a way to solve this without making every class that belong to an array of json objects be in it's own class?
Also it does not matter if the JsonProperty is above the set method. Any inner class that is not part of an array will also work.
private String sector_group;
#JsonProperty("underlyings")
private List<Underlyings> listUnderlyings;
#JsonProperty("tradables")
private List<Tradables> listTradables;
public class Underlyings {
private long instrument_id;
private String symbol;
private String isin_code;
public long getInstrument_id() {
return instrument_id;
}
public void setInstrument_id(long instrument_id) {
this.instrument_id = instrument_id;
}
public String getSymbol() {
return symbol;
}
public void setSymbol(String symbol) {
this.symbol = symbol;
}
public String getIsin_code() {
return isin_code;
}
public void setIsin_code(String isin_code) {
this.isin_code = isin_code;
}
}
Mapping method
ObjectMapper mapper = new ObjectMapper();
try {
String json = RestLogin.getBaseResource()
.path("instruments").path("lookup").path("market_id_identifier").path(market_id + ":" + identifier)
.request(RestLogin.getResponsetype()).get(String.class);
List<Instrument> tmpInstruments = mapper.readValue(json, mapper.getTypeFactory().constructCollectionType(List.class, Instrument.class));
Jackson and Inner Classes: yes, you can use, but they must be STATIC inner classes
Here's a snippet (but you should read the entire article for more explanation).
If you do not add static, resulting class is generally useless for Jackson as well as any other data binding framework (Hibernate, JAXB); can often be serialized, but never serialized into
I have a lot of subclasses of an abstract class and each of them declare a public static final field with the same name. I was thinking of having this field in the abstract superclass without initializing it and hoping that each subclass would be forced to initialize it.
I was thinking of this because all of my subclasses of the abstract class declare a public static final String field called UNIQUE_ID, and it is necessary for every subclass to declare such a field with exactly that name.
I hope my question is clear enough, if not please tell me so.
Can something more or less equivalent to this be done?
EDIT: Code added:
My abstract class looks like:
public abstract class ExperimentPanelModel extends Panelizable {
protected String nextButtonText;
protected String backButtonText;
protected String skipButtonText;
protected Properties currentFile;
protected List<Properties> pastFiles = new ArrayList<Properties>();
public ExperimentPanelModel(Properties argcurrentfile, List<Properties> argpastfiles) {
currentFile = argcurrentfile;
pastFiles = argpastfiles;
nextButtonText = "Next";
backButtonText = "Back";
skipButtonText = "Skip";
}
...
}
Some of the non-abstract subclasses of that abstract class look like (note that all of them declare public static final String UNIQUE_ID) :
public class ConfigurationGUI extends ExperimentPanelModel {
public static final String UNIQUE_ID = "ConfigurationGUI";
public static final String DATA_MODIFIED = "DataModified";
Date dateOfLastSession;
int ExperimentalSession;
int ExperimentOrder;
boolean nextButtonEnabled = false;
public ConfigurationGUI(Properties argcurrentfile, List<Properties> argpastfiles) {
super(argcurrentfile, argpastfiles);
nextButtonText = "Confirm";
backButtonText = "Abort";
}
...
}
One example more:
public class Introduction extends ExperimentPanelModel {
public static final String UNIQUE_ID = "Introduction";
public static final String INSTRUCTIONS_XML_FILE = "instructions.xml";
public static final String THIS_INSTRUCTION_PROPERTY = UNIQUE_ID;
private String thisInstructionText = UNIQUE_ID;
Properties readInstructionsProperties = new Properties();
public Introduction(Properties argcurrentfile, List<Properties> argpastfiles) {
...
And the last one:
public class Instruction1 extends ExperimentPanelModel {
public static final String UNIQUE_ID = "Instruction1";
public static final String INSTRUCTIONS_XML_FILE = "instructions.xml";
public static final String THIS_INSTRUCTION_PROPERTY = UNIQUE_ID;
...
}
The field idea won't work, because static fields can't be overridden in subclasses. What you can do is you can declare an abstract method on the abstract class so that your subclasses must implement it.
Also note you can't make it a static method because those don't get overridden either.
In your case I would define the variable in the ancestor. No point in having a variable in each of the extending classes, unless you have a particularly good reason, which you don't sound like having.
+1 for Nathan's reply though. In quite a few cases, that's a better thing to do.
Put the public final field UNIQUE-ID in the abstract class and declare a protected constructor which takes the value for UNIQUE-ID. You'll not be able to make it static though as the values are required to be different for different instances.
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.
I have a class with lots of final members which can be instantiated using one of two constructors. The constructors share some code, which is stored in a third constructor.
// SubTypeOne and SubTypeTwo both extend SuperType
public class MyClass {
private final SomeType one;
private final SuperType two;
private MyClass(SomeType commonArg) {
one = commonArg;
}
public MyClass(SomeType commonArg, int intIn) {
this(commonArg);
two = new SubTypeOne(intIn);
}
public MyClass(SomeType commonArg, String stringIn) {
this(commonArg);
two = new SubTypeTwo(stringIn);
}
The problem is that this code doesn't compile: Variable 'two' might not have been initialized. Someone could possibly call the first constructor from inside MyClass, and then the new object would have no "two" field set.
So what is the preferred way to share code between constructors in this case? Normally I would use a helper method, but the shared code has to be able to set final variables, which can only be done from a constructor.
How about this? (Updated for changed question)
public class MyClass {
private final SomeType one;
private final SuperType two;
public MyClass (SomeType commonArg, int intIn) {
this(commonArg, new SubTypeOne(intIn));
}
public MyClass (SomeType commonArg, String stringIn) {
this(commonArg, new SubTypeTwo(stringIn));
}
private MyClass (SomeType commonArg, SuperType twoIn) {
one = commonArg;
two = twoIn;
}
}
You need to make sure that in every constructor you are initializing all final variables. What I would do is have one constructor that initializes all the variables and have all the other constructor call that, passing in null or some default value if there is a field that they are not given a value for.
Example:
public class MyClass {
private final SomeType one;
private final SuperType two;
//constructor that initializes all variables
public MyClas(SomeType _one, SuperType _two) {
one = _one;
two = _two;
}
private MyClass(SomeType _one) {
this(_one, null);
}
public MyClass(SomeType _one, SubTypeOne _two) {
this(_one, _two);
}
public MyClass(SomeType _one, SubTypeTwo _two) {
this(_one, _two);
}
}
All you need to do is ensure that "two" gets initialized. In the first constructor, just add:
two = null;
unless there's some other value you'd like to give it in the event that only the first constructor is called.
You get this error because if you had called MyClass(SomeType oneIn), two is not initialized.
I have written some Java code with 3 simple classes where the first, Controller, has the main method and creates the instances of the other classes. Floaters is a classes that creates a linked list of Floater instances, each with a particular length and boolean value to say if they are vertical or not. My problem, as it says in the commented lines of the first class, is that both "humans" and "otters" Floaters instances are getting assigned the same values and thus have the same size....
Any suggestions on how to fix this?
Thanks in advance!
public class Controller{
private static Floaters humans;
private static Floaters otters;
public static void main(String[] args)
{
otters = new Floaters();
humans = new Floaters();
otters.addFloater(2, true);
otters.addFloater(3, true);
//this should read "2" and it does
System.out.println(otters.size());
//this should read "0" but reads "2". Why?
//How can I get it to read "0"?
System.out.println(humans.size());
}
}
import java.util.LinkedList;
public class Floaters {
private static LinkedList<Floater> llf;
Floaters()
{
llf = new LinkedList<Floater>();
}
public void addFloater(int length, boolean is_vertical)
{
Floater floater = new Floater(is_vertical, (byte)length);
llf.add(floater);
}
public int size()
{
return llf.size();
}
}
public class Floater {
int length;
boolean is_vertical;
Floater(boolean is_vertical, int length)
{
this.length = length;
this.is_vertical = is_vertical;
}
}
The llf in your Floaters-class is static. When you make variables static, they're linked to the class rather than the instance, and thus both instances of Floaters use the same list.
To correct this, simply remove the static from your declaration of the variable.
in floaters, llf should NOT be static
Because of static:
private static LinkedList<Floater> llf;
In this case static means a class field, shared among all instances of a class.
For example - mathematic functions in Java are declared as static metohods of the class java.lang.Math, matemathematical constants are static atributes of this class. So if you use sin(x), you are using always the same method.