Can someone tell me what the purpose of having inner classes? I can think of a few but may be they are not good reasons for using inner classes. My reasoning is that inner class is helpful when you want to use a class that no other classes can use. What else?
When I was learning Java we used inner classes for GUI event handling classes. It is sort of a "one time use" class that need not be available to other classes, and only is relevant to the class in which it resides.
Inner classes can be used to simulate closures: http://en.wikipedia.org/wiki/Closure_(computer_science)#Java
I use inner classes to define a structure that is best represented by the containing class, but doesn't necessarily make sense to use a separate external class to represent the structure.
To give an example I have a class that represents a particular type of network device, and the class has certain types of tests that can be run on that device. For each test there is also a potential set of errors that can be found. Each type of device may have a different structure for the errors.
With this you could do things like
List<Error> errors = RemoteDeviceA.getErrors();
With methods being available from the inner class, like
for ( Error error : errors ) {
System.out.println("MOnitor Type: " + error.getMonType());
...
}
Of course there are other ways to do this, this is just an inner class approach.
Simplified (aka incomplete) code for above:
public class RemoteDeviceA {
private String host;
private String user;
private String password;
private static List<Error> errors;
public RemoteDeviceA(String user, String host, String password) {
this.host = host;
this.user = user;
this.password = password;
login();
}
private void login() {
// Logs in
}
public void runTestA() {
List<Error> errorList = new ArrayList<Error>();
//loop through test results
if (!value.equals("0")) {
Error error = new Error(node, rackNum, shelfNum, slotNum, monType, value);
if (error.isError()) {
errorList.add(error);
}
}
setErrors(errorList);
}
private static void setErrors(List<Error> errors) {
RemoteDeviceA.errors = errors;
}
public List<Error> getErrors() {
return errors;
}
public class Error {
private String monType;
private String node;
private String rack;
private String shelf;
private String slot;
private String value;
private boolean error = false;
private boolean historyError = false;
private boolean critical = false;
private boolean criticalHistory = false;
Error(String node, String rack, String shelf, String slot,
String monType, String value) {
parseAlarm(node, rack, shelf, slot, monType, value);
}
private void parseAlarm(String node, String rack, String shelf,
String slot, String monType, String value) {
String modType = "";
if (monType.startsWith("ES_15") && !value.equals("0")) {
setMonType("ES_15");
setError(true);
} else if (monType.startsWith("SES_15") && !value.equals("0")) {
setMonType("SES_15");
setError(true);
} else if (monType.startsWith("BBE_15") && !value.equals("0")) {
setMonType("BBE_15");
setError(true);
} else if (monType.startsWith("UT_15") && !value.equals("0")) {
setMonType("UT_15");
setError(true);
setCritial(critical);
} else if (monType.startsWith("ES_24") && !value.equals("0")) {
setMonType("ES_24");
setHistoryError(true);
setError(true);
} else if (monType.startsWith("SES_24") && !value.equals("0")) {
setMonType("SES_24");
setHistoryError(true);
setError(true);
} else if (monType.startsWith("BBE_24") && !value.equals("0")) {
setMonType("BBE_24");
setHistoryError(true);
setError(true);
} else if (monType.startsWith("UT_24") && !value.equals("0")) {
setMonType("UT_24");
setHistoryError(true);
setError(true);
setCriticalHistory(true);
} else if (monType.startsWith("UT_15") && !value.equals("0")) {
setMonType("UT_15");
setError(true);
setCritial(true);
} else if (monType.startsWith("LASPWR")) {
float laserPwr = Float.valueOf(value);
if (node.startsWith("LEM_EM")) {
if ((laserPwr < 8.0) || (laserPwr > 12.0)) {
setMonType("LASERPWR");
setError(true);
}
} else if (node.startsWith("LEM10")) {
if ((laserPwr < 18.0) || (laserPwr > 22.0)) {
setMonType("LASERPWR");
setError(true);
}
}
}
if (isError()) {
setNode(node);
setRack(rack);
setShelf(shelf);
setSlot(slot);
setValue(value);
setError(true);
}
}
private void setMonType(String monType) {
this.monType = monType;
}
public String getMonType() {
return monType;
}
private void setNode(String node) {
this.node = node;
}
public String getNode() {
return node;
}
public void setRack(String rack) {
this.rack = rack;
}
public String getRack() {
return rack;
}
public void setShelf(String shelf) {
this.shelf = shelf;
}
public String getShelf() {
return shelf;
}
public void setSlot(String slot) {
this.slot = slot;
}
public String getSlot() {
return slot;
}
private void setValue(String value) {
this.value = value;
}
public String getValue() {
return value;
}
private void setError(boolean error) {
this.error = error;
}
public boolean isError() {
return error;
}
public void setCritial(boolean critical) {
this.critical = critical;
}
public boolean isCritical() {
return critical;
}
public void setCriticalHistory(boolean criticalHistory) {
this.criticalHistory = criticalHistory;
}
public boolean isCriticalHistory() {
return criticalHistory;
}
public void setHistoryError(boolean historyError) {
this.historyError = historyError;
}
public boolean isHistoryError() {
return historyError;
}
}
}
A list implementation that internally uses a linked list to store the elements could make good use of an inner class to represent the nodes within the list. I think you've hit the nail on the head by saying that you'd use such a class where you want to use it internally to a class but don't want it exposed - a 'one off' class that is only really useful 'here'.
I use inner classes (in C++) in situations where multiple classes, unrelated through inheritance, have conceptually similar implementation details, which form an implicit part of the public interface and ought to be named similarly.
class lib::Identifier { ... };
class lib::Person {
public:
class Identifier : public lib::Identifier { ... };
};
class lib::File {
public:
class Identifier : public lib::Identifier { ... };
};
This makes it convenient to refer to Identifier, Person::Identifier, and File::Identifier as simply Identifier, in the appropriate scopes.
Related
Writing the title was a bit tricky for this question :p
This is a basic java query!
I am using google cloud and it has different methods, such as launchInstance, listInstances and terminateInstance and so on.. Here, launchInstance will return a type String as Success or Fail, listInstances will return ArrayList, and so forth.
Now, I want a generic return type, so I made a class which has data entries such as status, reason, and dataRequired which will eventually send the data that is required, i.e String or ArrayList or HashMap.
How can I achieve this functionality.
Here is sample code that I was thinking of doing:
public class ResponseHelper {
private String status;
private String reason;
private String type;
private Object data;
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getReason() {
return reason;
}
public void setReason(String reason) {
this.reason = reason;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public void dataRequired(Object data) {
switch(getType()) {
case "ArrayList": this.data=(ArrayList<String>)data;
}
}
}
If you need a Generic return type of any object in Java, just return Object as the type.(Instead of creating a separate new class for it) Then you can check which object it is and do your stuff. Below is a simple program that you can get an idea out of it
public class GenericReturn {
public static void main(String[] args) {
Object output = returnMeSomething(2);
System.out.println(output.getClass().getSimpleName());
output = returnMeSomething(1);
System.out.println(output.getClass().getSimpleName());
output = returnMeSomething(0);
System.out.println(output.getClass().getSimpleName());
}
/** This can return any Object you want as it has Object as return type*/
public static Object returnMeSomething(int num) {
if (num == 1) {
return "Test";
}
else if (num == 2) {
return new HashMap();
}
return new ArrayList();
}
}
This output as below
HashMap
String
ArrayList
I have created a method in which i have multiple if conditions. Now i want to refactor these if conditions. What would be the best design pattern/strategy to overcome multiple if conditions?
if
(
poConfiguration.strSampleLoaderPluginClass != null
&& poConfiguration.strSampleLoaderPluginClass.equals("") == false
)
{
setSampleLoaderPluginClass(poConfiguration.strSampleLoaderPluginClass);
}
if
(
poConfiguration.strPreprocessingPluginClass != null
&& poConfiguration.strPreprocessingPluginClass.equals("") == false
)
{
setPreprocessingPluginClass(poConfiguration.strPreprocessingPluginClass);
}
if
(
poConfiguration.strFeatureExtractionPluginClass != null
&& poConfiguration.strFeatureExtractionPluginClass.equals("") == false
)
{
setFeatureExtractionPluginClass(poConfiguration.strFeatureExtractionPluginClass);
}
if
(
poConfiguration.strClassificationPluginClass != null
&& poConfiguration.strClassificationPluginClass.equals("") == false
)
{
setClassificationPluginClass(poConfiguration.strClassificationPluginClass);
}
Please share your thoughts with implementations, if possible. Thanks in advance
My first idea would be the polymorphism (Click here for more info), it depends from the concrete situation:
interface MyInterface {
public boolean checkCondition(PoConfiguration poConfiguration);
public void process(PoConfiguration poConfiguration);
}
public class SampleLoader implements MyInterface {
public boolean checkCondition(PoConfiguration poConfiguration) {
return poConfiguration.strSampleLoaderPluginClass != null
&& !poConfiguration.strSampleLoaderPluginClass.isEmpty();
}
public void process(PoConfiguration poConfiguration) {
setSampleLoaderPluginClass(poConfiguration.strSampleLoaderPluginClass);
}
}
public class ClientAPI {
public void caller() {
for (MyInterface current : this.myInterfaces) {
if (current.checkCondition(current)) {
current.process();
}
}
}
You might try something like the following:
Create a Configuration class that contains ConfigurationItems
Each ConfigurationItem would have a name, value and a default value
As an improvement, you may want to create static values for the configuration items instead of using Strings.
TestConfig main Class
package com.example.config;
public class TestConfig {
static TestConfig me;
static String[][] confSettings = {{"sampleLoader","loaderDefault"}
,{"preProcessing","preProcessingDefualt"}
,{"featureExtraction","featureExtractionDefault"}
,{"classification","classificationDefault"}
};
// Object fields
Configuration configuration;
public static void main(String[] args) {
// TODO Auto-generated method stub
me = new TestConfig();
me.doWork();
}
private void doWork() {
configuration = new Configuration();
for (int i=0; i < confSettings.length; i++) {
configuration.addConfigurationItem(confSettings[i][0], confSettings[i][1], null);
}
configuration.setConfigurationItemDefault("classification", "newValue");
System.out.println("sampleLoader = " + configuration.getConfigurationItemValue("sampleLoader"));
System.out.println("classification = " + configuration.getConfigurationItemValue("classification"));
}
}
Configuration Class
package com.example.config;
import java.util.ArrayList;
import java.util.HashMap;
public class Configuration {
// Class fields
// Object fields
HashMap<String,Integer> itemNames;
ArrayList<ConfigurationItem> items;
public Configuration() {
items = new ArrayList<ConfigurationItem>();
itemNames = new HashMap<String,Integer>();
}
public Configuration addConfigurationItem(String name, String defaultValue, String value) {
if (itemNames.containsKey(name)) {
// handle duplicate configuration item
} else {
items.add(new ConfigurationItem(name, defaultValue, value));
Integer loc = new Integer(items.size()-1);
itemNames.put(name, loc);
}
return this;
}
public void setConfigurationItemDefault(String name, String defaultValue) {
int loc = getConfigurationItemIndex(name);
if (loc > -1) {
items.get(loc).setDefaultValue(defaultValue);
}
}
public String getConfigurationItemValue(String name) {
int loc = getConfigurationItemIndex(name);
if (loc > -1) {
return items.get(loc).getValue();
} else {
// handle unknown parameter
return null;
}
}
private int getConfigurationItemIndex(String name) {
if (itemNames.containsKey(name)) {
return itemNames.get(name);
} else {
// handle unknown parameter
return -1;
}
}
}
ConfigurationItem Class
package com.example.config;
public class ConfigurationItem {
// Object fields
String name;
String value;
String defaultValue;
public ConfigurationItem(){};
public ConfigurationItem(String name, String defaultValue, String value) {
this.setName(name).setDefaultValue(defaultValue).setValue(value);
}
public ConfigurationItem setName(String name) {
this.name = name;
return this;
}
public ConfigurationItem setValue(String value) {
this.value = value;
return this;
}
public ConfigurationItem setDefaultValue(String defaultValue) {
this.defaultValue = defaultValue;
return this;
}
public String getValue() {
if (value == null || value.length() == 0) {
return defaultValue;
} else {
return value;
}
}
}
I am trying to iterate through an object that I have created and change some of its properties by using a get/set method. I managed to make it work when I only had one object, but now I have objects that inherit the parent object and each have slightly different properties that I want to change. E.g. a String, Float, Integer, Double object. At runtime I will not know which object will be found, so I want my Android application to be able to find it via a unique address and change the properties in the specific inherited object by iterating through the parent object. Please help me with this problem if anyone can. Thank you in advance.
Here is the parent object class code:
public class DataObject
{
private byte[] address;
private String type;
private boolean updatedFlag;
private boolean editedFlag;
public DataObject()
{
updatedFlag = false;
editedFlag = false;
}
public void setAddress(byte[] address)
{
this.address = address;
}
public void setType(String type)
{
this.type = type;
}
public void setUpdatedFlag(boolean updatedFlag)
{
this.updatedFlag = updatedFlag;
}
public void setEditedFlag(boolean editedFlag)
{
this.editedFlag = editedFlag;
}
public byte[] getAddress()
{
//return Arrays.toString(address);
return address;
}
public String getType()
{
return type;
}
public boolean getUpdatedFlag()
{
return updatedFlag;
}
public boolean getEditedFlag()
{
return editedFlag;
}
}
Here is one of the inherited object class:
public class DoubleDataObject extends DataObject
{
private double value;
private String range;
public DoubleDataObject()
{
}
public void setValue(double value)
{
this.value = value;
}
public void setRange(String range)
{
this.range = range;
}
public double getValue()
{
return value;
}
public String getRange()
{
return range;
}
}
And here is the code that iterates through the objects to change their properties:
private void setUpValues(byte[] address, byte[] value)
{
byte[] addressByteArray = address;
Iterator<DataObject> it = dataObjects.iterator();
while(it.hasNext())
{
DataObject currentDataObject = it.next();
byte[] dataObjectByteArray = currentDataObject.getAddress();
if(addressByteArray[0] == dataObjectByteArray[0])
{
System.out.println("Found subsystem!");
if(addressByteArray[1] == dataObjectByteArray[1])
{
System.out.println("Found highlevel!");
if(addressByteArray[2] == dataObjectByteArray[2])
{
System.out.println("Found low level!");
System.out.println("Found data object!");
currentDataObject.setValue(value);
currentDataObject.setUpdatedFlag(true);
System.out.println("Data Object Address: " + Arrays.toString(currentDataObject.getAddress()));
System.out.println("Data Object Type: " + currentDataObject.getType());
System.out.println("Data Object Value: " + currentDataObject.getValue());
System.out.println("Data Object Range: " + currentDataObject.getRange());
System.out.println("Data Object Updated Flag: " + currentDataObject.getUpdatedFlag());
System.out.println("Data Object Edited Flag: " + currentDataObject.getEditedFlag());
}
else
{
System.out.println("CANNOT FIND DATA OBJECT!");
}
}
else
{
System.out.println("CANNOT FIND HIGH LEVEL!");
}
}
else
{
System.out.println("CANNOT FIND SUBSYSTEM!");
}
}
}
You can check which class an object is and cast it to the subclass to access the methods,
is that waht you want to achieve?
DataObject currentDataObject = it.next();
if(currentDataObject instanceof DoubleDataObject){
DoubleDataObject doubleData = (DoubleDataObject) currentDataObject;
//check your methods
}
You can use this :
if (currentDataObject.getClass().equals(DoubleDataObject.class)) {
DoubleDataObject currentDoubleDataObject = (DoubleDataObject)currentDataObject;
currentDoubleDataObject .setValue(1.4d);
}
To test if the currentDataObject is a DoubleDataObject (and not a class inherit from a DoubleDataObject )
I have a method that return an object of a class.The object sets the properties of class and returns.
I have to traverse the object and get the value of the properties which the object has set before.
I tried to use for-each loop,iterator but failed to traverse.
Can someone please help me to get through this.Thanks in advance.
code:
public class ConsumerTool {
public MessageBean getMessages() {
MessageBean msgBean = new MessageBean();
msgBean.setAtmId(atmId.trim());
msgBean.setEventText(eventText.trim());
msgBean.setEventNumber(eventNumber.trim());
msgBean.setSeverity(severity.trim());
msgBean.setSubsystemID(subsystemID.trim());
msgBean.setUniqueEventID(uniqueEventID.trim());
msgBean.setTaskID(taskID.trim());
msgBean.setGenerator(generator.trim());
msgBean.setGeneratorBuildVsn(generatorBuildVsn.trim());
msgBean.setDateTime(dateTime.trim());
this.msgBean = msgBean;
return msgBean;
}
}
JavaBean class:
public class MessageBean implements java.io.Serializable {
public String dateTime;
public String severity;
public String eventText;
public String eventNumber;
public String generator;
public String generatorBuildVsn;
public String atmId;
public String uniqueEventID;
public String subsystemID;
public String taskID;
//System.out.println("dateTime2222222"+dateTime);
public String getAtmId() {
return this.atmId;
}
public void setAtmId(String n) {
this.atmId = n;
}
public String getDateTime() {
return this.dateTime;
}
public void setDateTime(String n) {
this.dateTime = n.trim();
}
public String getEventNumber() {
return this.eventNumber;
}
public void setEventNumber(String n) {
this.eventNumber = n;
}
public String getEventText() {
return this.eventText;
}
public void setEventText(String n) {
this.eventText = n;
}
public String getGenerator() {
return this.generator;
}
public void setGenerator(String n) {
this.generator = n;
}
public String getGeneratorBuildVsn() {
return this.generatorBuildVsn;
}
public void setGeneratorBuildVsn(String n) {
this.generatorBuildVsn = n;
}
public String getSeverity() {
return this.severity;
}
public void setSeverity(String n) {
this.severity = n;
}
public String getSubsystemID() {
return this.subsystemID;
}
public void setSubsystemID(String n) {
this.subsystemID = n;
}
public String getTaskID() {
return this.taskID;
}
public void setTaskID(String n) {
this.taskID = n;
}
public String getUniqueEventID() {
return this.uniqueEventID;
}
public void setUniqueEventID(String n) {
this.uniqueEventID = n;
}
}
The theme is the object sets the properties of javabean class and I have to get those values from UI.
In Jsp
<%
MessageBean consumer = msg.getMessages();
//Now here i want to iterate that consumer object
%>
As the MessagesBean seems to comply the javabeans specification, you can just use java.beans.Introspector for this.
MessageBean messageBean = consumerTool.getMessages();
// ...
BeanInfo beanInfo = Introspector.getBeanInfo(MessageBean.class);
for (PropertyDescriptor property : beanInfo.getPropertyDescriptors()) {
String name = property.getName();
Object value = property.getReadMethod().invoke(messageBean);
System.out.println(name + "=" + value);
}
This all is under the covers using the reflection API.
Update your edit reveals that you're intending to use this to present the data in JSP. This is then not really the right approach. Bite the bullet and specify every property separately. This way you've full control over the ordering.
I am refactoring a part of our legacy app which handles exporting and importing of DB tables from/to Excel sheets. We have a Formatter subclass for each table, to provide the definition of that table: how many columns it has, and what is the name, format and validator of each column. The getters which supply this data are then called by a Template Method which exports/imports the table. I have extracted the column data into an enum, which greatly simplified the code. A formatter now looks like this (some details omitted for brevity):
public class DamageChargeFormatter extends BaseFormatter {
public static final int NUM_COLUMNS = 7;
public enum Column {
VEHICLE_GROUP(0, "Vehicle Group", /* more params */),
NAME_OF_PART(1, "Name of Part", /* more params */),
//...
LOSS_OF_USE(6, "Loss of Use", /* more params */);
private static final Map<Integer, Column> intToColumn = new HashMap<Integer, Column>();
static {
for (Column type : values()) {
intToColumn.put(type.getIndex(), type);
}
}
public static TableColumn valueOf(int index) {
return intToColumn.get(index);
}
private int index;
private String name;
Column(int index, String name, /* more params */) {
this.index = index;
this.name = name;
//...
}
public int getIndex() { return index; }
public String getName() { return name; }
// more members and getters...
}
protected String getSheetName() {
return "Damage Charges";
}
public String getColumnName(int columnNumber) {
TableColumn column = Column.valueOf(columnNumber);
if (column != null) {
return column.getName();
}
return null;
}
// more getters...
protected int getNumColumns() {
return NUM_COLUMNS;
}
protected boolean isVariableColumnCount() {
return false;
}
}
Now, I have about a dozen such classes, each of which containing exactly the same code except that NUM_COLUMNS and the enum values of Column are different. Is there any way to genericize this somehow? The main obstacle to this is the static Column.valueOf() method and the static constant NUM_COLUMNS. Another concern with latter is that it really belongs to an abstraction one level higher, i.e. to the table, not to an individual column - it would be nice to somehow incorporate this into the generic solution.
Technically I could solve this with a base interface (TableColumn below) and reflection, but I don't really like that, as apart from trading compile time errors to runtime errors, it makes the code ugly (to me):
public class GenericFormatter<E extends TableColumn> extends BaseFormatter {
private Method valueOfMethod;
public GenericFormatter(Class<E> columnClass) {
try {
valueOfMethod = columnClass.getDeclaredMethod("valueOf", Integer.class);
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
}
}
public String getColumnName(int columnNumber) {
try {
#SuppressWarnings("unchecked")
E elem = (E) valueOfMethod.invoke(columnNumber);
if (elem != null) {
return elem.getName();
}
} catch (Exception e) {
throw new RuntimeException(e);
}
return null;
}
//...
}
Note that this code is purely experimental, as yet untested...
Is there a nicer, cleaner, safer way?
May be, something like this:
public class TableMetadata<E extends Enum & TableColumn> {
private Map<Integer, TableColumn> columns = new HashMap<Integer, TableColumn>();
public TableMetadata(Class<E> c) {
for (E e: c.getEnumConstants()) {
columns.put(e.getIndex(), e);
}
}
public String getColumnName(int index) {
return columns.get(index).getName();
}
}
public class GenericFormatter<E extends TableColumn> extends BaseFormatter {
private TableMetadata<E> m;
public GenericFormatter(TableMetadata<E> m) {
this.m = m;
}
public String getColumnName(int columnNumber) {
return m.getColumnName(index);
}
//...
}
EDIT: Enum added to the type parameter for more compile-time safety