I am creating an API that returns a list of Cars. The API user must be able to request that the list be filtered and sorted by a certain attribute (field) of the Cars class. How can I do that?
class Car {
public final String model;
public final String color;
public Car(String m, String c) {
model = m;
color = c;
}
}
class CarListRequest {
public final String sortBy;
public final String filterBy;
public final List<String> filterList;
public CarListRequest(String s, String f, List<String> list) {
sortBy = s;
filterBy = f;
filterList = list;
}
}
Is there a way to restrict, using Java language features, that sortBy and filterBy Strings cannot contain any other values than attributes (fields) of the Car class?
I know that I could use an enum to declare all attributes of Car however, that causes a duplication of Strings which I would like to avoid.
#hmc_jake 's reflection suggestion is quite valid. However, if you want to avoid reflection, you could do it using a class hierarchy:
class CarAttribute {
private String attrib;
public CarAttribute(String att){
attrib = att;
}
// add getters and/or setters for attrib ...
}
class CarModel extends CarAttribute {
}
class CarColor extends CarAttribute {
}
class Car {
public final CarModel model;
public final CarColor color;
public Car(CarModel m, CarColor c) {
model = m;
color = c;
}
}
class CarListRequest {
public final CarAttribute sortBy;
public final CarAttribute filterBy;
public final List<CarAttribute> filterList;
public CarListRequest(CarAttribute s, CarAttribute f, List<CarAttribute> list) {
sortBy = s;
filterBy = f;
filterList = list;
}
}
Using Reflection in Java, it is possible to inspect a class's fields.
When, for example, s is passed in, you can perform a check on the argument like so:
for (Field field : Car.class.getFields()) {
if (field.getName().equalsIgnoreCase(s)) {
Do something here to signal that s
was a valid Field of the Car class.
}
}
Doing this allows you to reflectively inspect the Car class in order to verify that the argument passed in is in-fact a field of that class.
Note, however, that if possible you should go with the enum or class hierarchy as reflection might be a little bit overkill for what you're trying to accomplish.
Related
I have a few enums that have the same functionality but contain different constants for organization reasons. They each look like this:
public enum OneEnum {
greenApple(apple, green),
redApple(apple,red);
private final String fruit;
private final String type;
private OneEnum (final String fruit, final String type) {
this.fruit = fruit;
this.type = type;
}
public String getFruit() {
return fruit;
}
public String getType() {
return type;
}
}
The other enums have the same private fields, constructor, and methods and only differ by listed constants. I was wondering how much of this code I can move to a common place such as interface (or abstract class if possible). I am able to create an interface such as:
public interface CommonEnum {
String getFruit();
String getType();
}
but can I do better than that?
You could do something like this:
public interface CommonEnum { ...
public class Holder implements CommonEnum() {
private final String fruit ...
}
public enum OneEnum {
GREEN_APPLE(new Holder(GREEN, APPLE)), ...
private OneEnum(Holder holder) { this.holder = holder };
public getHolder() { return holder };
In other words: if that "combination" of values is the "common thing" that you need in different places, than that should go into its own class.
Of course, the downside of this is: users of your enum would now be violating the Law of Demeter, as in:
Fruit fruit = OneEnum.GREEN_APPLE.getHolder().getFruit();
I don't at all see the point in using an enum for the combination of values at all.
What you have in effect is
public enum Fruit {
APPLE, ORANGE, BANANA //...
}
public enum Color {
RED, GREEN, BLUE // ...
}
and a combination of the two
class ColoredFruit {
public final Fruit fruit;
public final Color color;
public ColoredFruit(Fruit f, Color c) { fruit = f; color = c; }
}
The enums you have are only instances
Collection<ColoredFruit> apples = Arrays.asList(new ColoredFruit(APPLE, RED), new ColoredFruit(APPLE, GREEN));
And if you do feel fancy, add interfaces
interface Fruit {
FruitEnum getFruit();
}
interface Colored {
Color getColor();
}
which ColoredFruit can implement by adding getters.
I'm trying to find a good way to orginize a group of constant values that are used simply for immutable data.
Here is what I'm currently attempting:
public class FishType {
//PredatorFishType extends FishType
public static final PredatorFishType SHARK = new PredatorFishType(5, 20, "Shark");
public static final FishType CAT_FISH = new FishType("Cat Fish");
private String name;
private FishType(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
I use reflection to gather the final values into a collection aswell. I used to utilize enum but was forced to think of a new way to do this when different types of fish came into play such as the predator which contains other data such as food and so on. These constants are only used for data displaying purposes and have no reason to be mutated.
If there is some way to have multiple enum types within the same enum (If that makes any sense at all), that'd be great.
Thanks for reading.
You can either use constructor overloading or a combination of overloading and a wrapper class. If you know for certain that this data is immutable and will always be that way, I don't see anything wrong with sticking to enums for it. For the sake of putting it into one class, I've included the enums in the EnumTester class, but you may not want to do that.
Here's an example that prints "Cat Fish 5 20 Shark" and "Cow Fish" when run, using nothing but enums and a wrapper class. You could put accessors wherever you need them, depending on what you actually want to do with the information - I'm trying to demonstrate how to compose the two enums, not how to use them.
package enums;
public class EnumTester
{
public enum MainType {
CAT_FISH("Cat Fish"), DOG_FISH("Dog Fish"), COW_FISH("Cow Fish"); //everything has a name...
private String name;
private MainType(String name){
this.name = name;
}
public String getTypeDetails(){
return name;
}
}
public enum SubType {
PREDATOR(5, 20, "Shark"), PREY(), MANATEE(); //but not everything has any additional information
private boolean isFullSubType;
private int val1;
private int val2;
private String subName;
private SubType(int val1, int val2, String subName){
this.isFullSubType = true;
this.val1 = val1;
this.val2 = val2;
this.subName = subName;
}
private SubType(){
this.isFullSubType = false;
this.val1 = -1;
this.val2 = -1;
this.subName = "none";
}
public String getSubTypeDetails()
{
if( isFullSubType ) {
return val1 + " " + val2 + " " + subName;
}
else {
return "";
}
}
}
private MainType mainType;
private SubType subType;
public EnumTester(MainType mainType, SubType subType)
{
this.mainType = mainType;
this.subType = subType;
}
public static void main(String[] args)
{
EnumTester kittyShark = new EnumTester(MainType.CAT_FISH, SubType.PREDATOR);
System.out.println(kittyShark.printDetails());
EnumTester cowManatee = new EnumTester(MainType.COW_FISH, SubType.MANATEE);
System.out.println(cowManatee.printDetails());
}
public String printDetails(){
return mainType.getTypeDetails()+" "+subType.getSubTypeDetails();
}
}
I typically follow a similar pattern to what you've done above. I might make the class FishTypes to be the collector, just to keep the FishType interface a bit cleaner. You can also invent some syntactic sugar to help you collect registered FishTypes:
public static final Set<FishType> registeredFish = new HashSet<>();
public static final PredatorFishType SHARK = register(new PredatorFishType(5, 20, "Shark"));
public static final FishType CAT_FISH = register(new FishType("Cat Fish"));
public static <T extends FishType> T register(T fishType) {
registeredFish.add(fishType);
return fishType;
}
I have an abstract class which has a method used by all classes that extend the class. That method is identical for each class so I don't want to have to write it over and over in those classes. The problem is that the method uses 2 variables that are declared in each class. I can't have the method in the abstract class without having those variables int eh abstract class. But if I do that, they take on the value specified in the abstract class, not the classes that extend it. How can I fix this?
Example code:
public abstract class Example {
public String property1 = ""
public String property2 = ""
public ArrayList<String> getPropertyies() {
ArrayList<String> propertyList = new ArrayList<>();
propertyList.add(property1);
propertyList.add(property2);
return property1;
}
}
public class ExampleExtension extends Example {
public String property1 = "this is the property";
public String property2 = "this is the second property";
}
You should limit the scope of the fields to private in the abstract class and declare a constructor for populating the values:
public abstract class Example {
private final String property1;
private final String property2;
protected Example(String property1, String property2) {
this.property1 = property1;
this.property2 = property2;
}
//...
}
Subclasses would then initialize the field values in their constructors by calling the super constructor:
public class ExampleExtension extends Example {
public ExampleExtension() {
super("value1", "value2");
// initialize private fields of ExampleExtension, if any
}
// ...
}
You don't have to override the variables. You can set the initial values of your properties in the constructor:
public class ExampleExtension extends Example {
public ExampleExtension() {
property1 = "this is the property";
property2 = "this is the second property";
}
}
A better way is to use a constructor with parameters though, as Mick Mnemonic suggest in the other answer.
IMO Mick's solution is the most pragmatic, although note that you also have the option to make the properties abstract, and then use subclass polymorphicism to require that subclasses override the property implementation:
public abstract class Example {
public abstract String getProperty1();
public abstract String getProperty2();
public ArrayList<String> getPropertyies() {
ArrayList<String> propertyList = new ArrayList<>();
propertyList.add(getProperty1());
propertyList.add(getProperty2());
return propertyList;
}
}
public class ExampleExtension extends Example {
public String getProperty1() { return "this is the property"};
public String getProperty2() { return "this is the second property"};
}
Make what differs(e.g. property1,property2) abstract method in this case . Search for related reading on template pattern
public abstract class Example {
public ArrayList<String> getPropertyies() {
ArrayList<String> propertyList = new ArrayList<>();
propertyList.add(getProperty1());
propertyList.add(getProperty2());
return property1;
}
public abstract getProperty1();//overriden by other class that has diff value for property1
public abstract getProperty2();//overriden by other class that has diff value for property2
}
I have a List named resourceItems which containes ResourceItem objects.
public class ResourceItem {
private Long id;
private String name;
public ResourceItem(Long id, String name) {
this.id = id;
this.name = name;
}
// getters and setters...
}
public class SomeClass {
private List<ResourceItem> resourceItems = FindAllResourcesWebSerbice();
}
I would like to extend the objects in the List to include a boolean field named selected.
I've tried several variations of classes that extends ResourceItem (see below) including options using generics, but have not been successful. I would love a solution that uses generics for reuse.
public class ExtendedResourceItem extends ResourceItem {
private boolean selected = false;
public ExtendedResourceItem() {
}
public boolean isSelected() {
return selected;
}
public void setSelected(boolean selected) {
this.selected = selected;
}
}
public class SomeClass {
private List<ResourceItem> resourceItems = FindAllResourcesWebSerbice();
private List<ExtendedResourceItem> extendedResourceItem = resourceItems;
}
Any help is much appreciated.
Assuming ResourceItem implements equals and hashCode correctly, why not just keep a set of the ones that are selected:
Set<ResourceItem> selectedResourceItems = new HashSet<ResourceItem>();
Then you could add an item to the set when it's selected, remove it when it's deselected, and check to see if the set contains one when you need to know if it's selected.
This solution is very similar to Michael Myers' comment about using a Map<ResourceItem, Boolean>.
You should use composition, not inheritance here. From your description it sounds like ResourceItem is a domain object, but on screen, you should wrap it
class ScreenResourceItem {
ResourceItem item;
boolean selected;
}
Create a new list of ScreenResourceItem and put all the wrapped ResourceItems in it.
Generics and list covariance are not relevant here.
But using your snippet:
private List<ResourceItem> resourceItems = ... \\ some assignment;
private List<ExtendedResourceItem> extendedResourceItems = resourceItems;
is absolutely wrong. Since not any ResourceItem is guarantee to be also ExtendedResourceItem. (resourceItems list can contain objects that are ResourceItem but are NOT ExtendedResourceItem).
I don't see the point you want to reach, but if You want to transform resourceItems into list of resourceItems that have selected attribute, what about this concept:
public class ExtendedResourceItem {
private ResourceItem item = null;
private boolean selected = false;
public ExtendedResourceItem(ResourceItem item, boolean selected) {
this.item = item;
this.selected = selected;
}
// ... getters and setters
}
public class SomeClass {
private List<ResourceItem> resourceItems = FindAllResourcesWebSerbice();
private List<ExtendedResourceItem> extendedResourceItems = new ArrayList<ExtendedResourceItem>();
for (ResourceItem item: resourceItems) {
extendedResourceItems.add(new ExtendedResourceItem(item, false));
}
}
Is it the generics limits that are confusing? Try using the Upper Bounded Wildcards, e.g.
public class SomeClass {
private List<ExtendedResourceItem> extendedResourceItems = FindAllResourcesWebSerbice();
private List<? extends ResourceItem> resourceItems = extendedResourceItems;
}
Alternatively:
public class SomeClass {
private List<? extends ExtendedResourceItem> extendedResourceItems = FindAllResourcesWebSerbice();
private List<? extends ResourceItem> resourceItems = extendedResourceItems;
}
More information about wildcards Wildcards and Subtyping.
I have several interfaces all with the same constants - ID and ROOT. I also have a method into which I pass an object that will be an implementation of one of these interfaces.
How can I dynamically retrieve the value of the constant depending on the class passed in - i.e. I want to do something like the following:
public void indexRootNode(Node node, Class rootNodeClass)
{
indexService.index(node, rootNodeClass.getConstant('ID'),
rootNodeClass.getConstant('ROOT'));
}
In PHP this is easy, but is this possible in Java? I've seen this problem solved using accessors on the constant, but I want to retrieve the constant directly. Annotations won't help me here either.
Thanks
This can be achieved using reflection (also see corresponding javadoc).
public void indexRootNode(Node node, Class rootNodeClass)
{
Field idField = rootNodeClass.getField("ID");
Object idValue = idField.get(null);
Field rootField = rootNodeClass.getField("ROOT");
Object rootValue = rootField.get(null);
indexService.index(node, idValue, rootValue);
}
Maybe you may additionaly have to cast the values to the corresponding type.
Please read chapter 19 use interfaces only to define types from Joshua Bloch's Effective Java (in fact, please read the entire book)
Constants do not belong in an interface!!! Constants should be tied to implementing classes, not interfaces.
Either use non-constant methods:
// the implementing classes can define these values
// and internally use constants if they wish to
public interface BaseInterface{
String id(); // or getId()
String root(); // or getRoot()
}
public interface MyInterface1 extends BaseInterface{
void myMethodA();
}
public interface MyInterface2 extends BaseInterface{
void myMethodB();
}
or use an enum to tie things together:
public enum Helper{
ITEM1(MyInterface1.class, "foo", "bar"),
ITEM2(MyInterface2.class, "foo2", "baz"),
;
public static String getId(final Class<? extends BaseInterface> clazz){
return fromInterfaceClass(clazz).getId();
}
public static String getRoot(final Class<? extends BaseInterface> clazz){
return fromInterfaceClass(clazz).getRoot();
}
private static Helper fromInterfaceClass(final Class<? extends BaseInterface> clazz){
Helper result = null;
for(final Helper candidate : values()){
if(candidate.clazz.isAssignableFrom(clazz)){
result = candidate;
}
}
return result;
}
private final Class<? extends BaseInterface> clazz;
private final String root;
private final String id;
private Helper(final Class<? extends BaseInterface> clazz,
final String root,
final String id){
this.clazz = clazz;
this.root = root;
this.id = id;
};
public String getId(){
return this.id;
}
public String getRoot(){
return this.root;
}
}
// use it like this
String root = Helper.fromInterfaceClass(MyInterface1.class).getRoot();