Can I reference a class by String name? - java

I have a list of utilities that derive from:
abstract public class BaseUtil implements Callable{
public String name;
public StreamWrapper data;
public void setData(StreamWrapper stream){ this.data = stream; }
private static Class me = BaseUtil.class;
private static Method[] availableUtilities = me.getDeclaredMethods();
public static Method[] getUtilities(){ return availableUtilities; }
}
I want to, at each node, be able to assign a utility to it, something like:
Initialize(String utilName){
activeUtility = utilName;
gk = new GateKeeper(BaseUtil.getUtilities() <something>);
}
public class GateKeeper {
GateKeeper(BaseUtil util) {
this.util = util;
}
private BaseUtil util;
But I'm unsure on how to get the specific utility class from just the String passed in. An example utility is:
public class WordLengthUtil extends BaseUtil {
private String name = "WordLength";
public Integer call() {
System.out.println(this.data);
return Integer.valueOf(this.data.length());
}
}

You can use reflection:
String name = "WordLength";
String className = hashMap.get(name);
Callable plugin = (Callable) Class.forName(className).newInstance();
use HashMap to store binding between className and string identifier

Related

Limit instance construction to an external factory

The pattern I'm aiming for is to put all the classes that I want clients to use - like model objects, interfaces and factories - in a "client" package and put the private implementation in an impl package that is inaccessible to clients.
I only want clients to access my API using interfaces and I want to prevent them from instantiating private implementation classes directly.
What follows is a simple example. It works but am wondering if there's a better way - I'd imagine that this is a commonly used pattern?
package client;
public interface Plant {
String getScientificName();
String getCommonName();
}
package client;
import impl.PlantImpl;
import java.util.function.BiFunction;
public final class PlantFactory {
private BiFunction<String, String, Plant> delegate;
public PlantFactory() {
PlantImpl.registerFactory(this);
}
public void setFactory(BiFunction<String, String, Plant> factory) {
delegate = factory;
}
public Plant newInstance(String scientificName, String commonName) {
return delegate.apply(scientificName, commonName);
}
}
package impl;
import client.Plant;
import client.PlantFactory;
import java.util.function.BiFunction;
public final class PlantImpl implements Plant {
private final String scientificName;
private final String commonName;
private PlantImpl(String scientificName, String commonName) {
this.scientificName = scientificName;
this.commonName = commonName;
}
#Override
public String getScientificName() {
return scientificName;
}
#Override
public String getCommonName() {
return commonName;
}
public static void registerFactory(PlantFactory plantFactory) {
plantFactory.setFactory(new Factory());
}
static class Factory implements BiFunction<String, String, Plant> {
#Override
public Plant apply(String scientificName, String commonName) {
return new PlantImpl(scientificName, commonName);
}
}
}
import client.Plant;
import client.PlantFactory;
public final class PlantViewer {
public static void main(String[] args) {
// Doesn't compile due to private constructor
// Plant wattle = new PlantImpl("Acacia longifolia", "Sydney Golden Wattle");
PlantFactory plantFactory = new PlantFactory();
Plant grevillea = plantFactory.newInstance("Grevillea caleyi", "Caley's Grevillea");
System.out.println("Plant name is " + grevillea.getCommonName());
}
}

Java: Access class within a method

I would like have one method declare two Strings and assign them values. Then have another method to read those values.
I have this structure:
public class ABC extends CDE implements EFG {
public void firstMethod(valueOne, valueTwo) {
class TestClass {
public String testValue = valueOne;
public String anotherValue = valueTwo;
}
}
public void readMethod() {
// HERE I WANT TO READ testValue AND ASSIGN IT A NEW VALUE
}
}
How can I do that?
And is there a better way?
Are you sure you need a class?
May be a simple field declaration will be enough:
public class ABC extends CDE implements EFG {
public String testValue;
public String anotherValue;
public void firstMethod(String valueOne, String valueTwo) {
// do whatever you wish with testValue and anotherValue
}
public void readMethod() {
// here you have access to both variables
}
}
Make the local class global and set/read values via instance:
public class ABC extends CDE implements EFG {
class TestClass {
public String testValue = valueOne;
public String anotherValue = valueTwo;
}
private testClassInstance = new TestClass()
public void firstMethod(valueOne, valueTwo) {
testClassInstance.testValue = valueOne
testClassInstance.anotherValue = valueTwo
}
public void readMethod() {
System.out.println(testClassInstance.valueOne)
System.out.println(testClassInstance.valueTwo)
}
}
All you want to do is to create a POJO that holds testValue and anotherValue and declare the class outside of your component class, e.g.:
class ExampleBean {
private String testValue;
private String anotherValue;
//getters and setters
}
Once done, you can hold the reference of that class into your component class and access the value, e.g.:
public class ABC extends CDE implements EFG {
ExampleBean exampleBean = new ExampleBEan();
public void firstMethod(valueOne, valueTwo) {
exampleBean.setValueOne(valueOne);
exampleBean.setAnotherValue(valueTwo);
}
public void readMethod() {
String value = exampleBean.getValueOne();
}
}
Maybe this will fit your criteria?
What you are currently asking for is impossible due to the scope of the inner class.
You could also initialize this private class instance in your constructor.
public class Sample {
class TestClass {
public String testValue;
public String anotherValue;
}
private TestClass localTest = new TestClass();
public void firstMethod(valueOne, valueTwo) {
localTest.testValue = valueOne;
localTest.anotherValue = valueTwo;
}
public void readMethod() {
localTest.testValue = "test1";
localTest.anotherValue = "anotherValue";
System.out.println(localTest.testValue);
}
}
You are declaring a class withing a method , which is not right
You need to understand what a class and a method really mean ( Google Java OOP ) :
1- You should create a class and declare the variables you want
2- make constructors for the default values
3- make setters to set (assign) these values
4- make getters to read those values

Creating a generic function in Java for builders of different implementations of interface

public interface A extends C {
String getCh();
String getId();
String getReview();
}
public interface B extends C {
String getCh();
String getId();
String getReview();
}
#Data
#Builder
public class AImpl implements A{
private String ch;
private String id;
private String review;
}
#Data
#Builder
public class BImpl implements B{
private String ch;
private String id;
private String review;
}
so now to use the builders of these I do:
return AImpl.builder()
.ch("ch")
.id("id")
.review("somerview");
For B I do:
return BImpl.builder()
.ch("ch1")
.id("id1")
.review("some new review");
Is there a way where I can make this builder part into a function? I dont like the idea of repeating the same code again. Like where I can pass id channel and review in a function and I can the object?
Disclaimer: I have never really dealt with builders so there might be a really much better option :D
This approach writes builders for each interface individually.
This does require that the interfaces provide a setter method.
Using generics, the methods of the RootBuilder and BaseABuilder return an instance of the ImplABuilder so that the chain can continue properly.
This is a very simple implementation of the Thistype generic which in other languages exists by default. This implementation also relies on casting to the actual Thistype but if you set the generics properly, that shouldnt be an issue.
public class Test
{
public static void main(String[] args)
{
ImplA implA = ImplA
.builder()
.id("id")
.description("description")
.valueA("a")
.build();
}
}
public interface Root
{
String getId();
void setId(String id);
String getDescription();
void setDescription(String description);
}
public class RootBuilder<Thistype extends RootBuilder<Thistype, Instance>, Instance extends Root>
{
protected final Instance object;
RootBuilder(Instance object)
{
this.object = object;
}
public Thistype id(String value)
{
object.setId(value);
return (Thistype)this;
}
public Thistype description(String value)
{
object.setDescription(value);
return (Thistype)this;
}
public Instance build()
{
return object;
}
}
public interface BaseA extends Root
{
String getValueA();
void setValueA(String valueA);
}
public class BaseABuilder<Thistype extends BaseABuilder<Thistype, Instance>, Instance extends BaseA> extends RootBuilder<Thistype, Instance>
{
protected Instance object;
BaseABuilder(Instance object)
{
super(object);
}
public Thistype valueA(String value)
{
object.setValueA(value);
return (Thistype)this;
}
}
public interface BaseB extends Root
{
String getValueB();
void setValueB(String valueB);
}
public interface BaseC extends Root
{
String getValueC();
void setValueC(String valueC);
}
public final class ImplA implements BaseA
{
private String id;
private String description;
private String valueA;
private ImplA() { }
public static ImplABuilder builder()
{
return new ImplABuilder(new ImplA());
}
private static class ImplABuilder extends BaseABuilder<ImplABuilder, ImplA> // assuming ImplA is final
{
ImplABuilder(ImplA object)
{
super(object);
}
// additional methods for ImplA class
}
}

Declaring a nested class in Java

I'm a bit confused with subclasses.
Here's my code:
public class MedHistory {
private String grafts;
private String allergies;
private String diseases;
private String surgeries;
private String medicalTreatment;
//Constructors (#2)
public MedHistory(String allergies, String diseases, String grafts,
String treatments, String surgeries) {
this.allergies=allergies;
this.diseases=diseases;
this.grafts=grafts;
this.medicalTreatment=treatments;
this.surgeries=surgeries;
}
public MedHistory() {
this.allergies="";
this.diseases="";
this.grafts="";
this.medicalTreatment="";
this.surgeries="";
}
//Getters
public String getGrafts() {
return grafts;
}
public String getAllergies() {
return allergies;
}
public String getDiseases() {
return diseases;
}
public String getSurgeries() {
return surgeries;
}
public String getMedicalTreatment() {
return medicalTreatment;
}
//Setters
public void setGrafts(String grafts) {
this.grafts = grafts;
}
public void setAllergies(String allergies) {
this.allergies = allergies;
}
public void setDiseases(String diseases) {
this.diseases = diseases;
}
public void setSurgeries(String surgeries) {
this.surgeries = surgeries;
}
public void setMedicalTreatment(String medicalTreatment) {
this.medicalTreatment = medicalTreatment;
}
public class FemMedHistory extends MedHistory {
private List<Birth> births = new ArrayList<Birth>();
//Constructors (#2)
public FemMedHistory(String allergies, String diseases, String grafts,String treatments, String surgeries, List<Birth> birthlist) {
super(allergies,allergies,grafts,treatments,surgeries);
this.births=birthlist;
}
public FemMedHistory() {
super();
this.births=null;
}
//Getter
public List<Birth> getBirths() {
return this.births;
}
//Setter
public void setBirths(List<Birth> list) {
this.births=list;
}
}
}
When I try to create an new FemMedHistory object like this:
List<Birth> list = new ArrayList<Birth>();
list.add(new Birth(new GregorianCalendar(2011,4,10),"kaisariki",4));
FemMedHistory female = new FemMedHistory("allergia2","astheneia2","emvolia2","farmekeutiki agwgi2", "xeirourgeia2", list);
I get the error:
No enclosing instance of type MedHistory is accessible. Must qualify
the allocation with an enclosing instance of type MedHistory (e.g.
x.new A() where x is an instance of MedHistory).
So, which is the right way to use a subclass?
When you declare a nested class it only available through the Outer class.
To access it outside, you will need to either make the FemMedHistory class static.
public static class FemMedHistory extends MedHistory {...}
access it through the MedHistory class
MedHistory.FemMedHistory myMedHistory = ...
or declare it in it's own Java file.
You have declared your subclass as an inner class, which means that you can't create an instance of it without first creating an instance of the containing class.
The most common way to solve this is to declare it as a separate class, which would get rid of your error.
Long story short: cut all the FemMedHistory code and paste it into FemMedHistory.java. The way it is now you have involved Java concepts which you have not yet mastered. Also, that class really does belong in a separate file.

Getting current object properties when calling an undeclared super method from abstract class

Probably a very basic java question.
I have an abstract class, simplifying it:
public abstract class A{
private String value = "A" ; // I want it undeclared, but set it for testing purpouse
public String getValue(){
return value ;
}
}
Then I have a class extending it:
public abstract class B{
private String value = "B" ;
}
So the problem I have is, when creating an instance of B through class A, and calling getValue(), it always return "A":
A b = new B();
b.getValue(); // returns "A"
How can I get B calling super method using his own properties without having to duplicate code? A it is currently too long, and it is extended to many different class that only differs by it properties values and all of them use the same methods that the super class has.
Thanks!
Edit:
Sorry, I wasn't so specific. I have a lot of properties, and some methods to deal with those properties. Extended class change those properties, but I want to use the super methods with the extended class instanced object without having to declare them twice. I'm working with servlets context atributtes if that helps.
Config.java
public abstract class Config {
private String someValue1 ;
...
private String someValuen ;
public void export(ServletContext cxt){
cxt.setAttribute("someValue1", someValue1);
...
cxt.setAttribute("someValuen", someValuen);
}
}
SomeConfig.java
public class SomeConfig {
private String someValue1 = "something" ;
...
private String someValuen = "something else" ;
}
SomeServlet.java
ServletContext cxt = getServletContext() ;
Config config = new SomeConfig();
config.export(cxt);
To make it clear, properties all have different names. I use them from jsp as: ${someValuen}
The reason why it doesn't work is that only methods can be overriden - variable members are hidden instead (if you print value from your B class, it will be "B").
For that specific example I would use a dedicated constructor (which I have made protected to prevent client classes from accessing it):
public abstract class A {
private final String value;
public A() { //for internal / testing use only
value = "A";
}
protected A(String value) {
this.value = value;
}
public String getValue(){
return value ;
}
}
Then B can simply call the relevant constructor:
public class B extends A {
public B() {
super("B");
}
}
EDIT
Example with a ConfigHolder:
public class ConfigHolder {
String value1;
String value2;
String value3;
public ConfigHolder value1(String value1) {
this.value1 = value1;
return this;
}
//same for other variables
}
Then in class A:
public abstract class A {
private final ConfigHolder config;
public A() {
this.config = new ConfigHolder()
.value1("value1")
.value2("value2");
}
protected A(ConfigHolder config) {
this.config = config;
}
public void export(ServletContext cxt){
cxt.setAttribute("someValue1", builder.value1);
...
cxt.setAttribute("someValuen", builder.valuen);
}
}
And in B:
public class B extends A {
public B() {
super(new ConfigBuilder()
.value1("value1InB")
.value2("value2InB"));
}
}
To do this: A b = new B(); B must be a subclass of A
Besides, an abstract class can not be instantiated, ie can not create abstract class objects. The compiler will produce an error if you try to.
public abstract class A{
private String value = "A" ;
public String getValue(){
return value ;
}
}
public class B extends A{
private String value ;
public B(){
value = "B";
}
}
Now you can do B notAbstractClass = new B();
And when doing notAbstractClass.getValue(); it must return "B"
I just figured out a simple way to do it with a constructor and changing the super class properties to protected (thanks to #assylias answer):
Config.java
public abstract class Config {
protected String someValue1 ;
...
protected String someValuen ;
public void export(ServletContext cxt){
cxt.setAttribute("someValue1", someValue1);
...
cxt.setAttribute("someValuen", someValuen);
}
}
SomeConfig.java
public class SomeConfig {
public SomeConfig(){
someValue1 = "something";
...
someValuen = "something else";
}
}

Categories

Resources