I am making a new class that accepts a list of objects as an argument.
However I want to make it so these objects can be anything as long as they have certain methods, for example a .getValue() method that returns a single double, or a .getTimestamp() method that returns a single long, etc.
Can this be done?
You can use an interface or implementation inheritance,
interface Foo{
long getTimestamp();
}
class Bar implements Foo{
... impl ..
}
And then your methods will take a List of subtypes of Foo ( the super type)
void fn(List<? extends Foo> foos){
for(Foo foo:foos){
long time = foo.getTimestamp();
}
}
You can do this by using an interface, as long as you're defining these objects:
interface MyInterface {
double getValue();
long getTimestamp();
}
class MyClass1 implements MyInterface {
#Override
public double getValue() {
// ...
}
#Override
public long getTimestamp() {
// ...
}
}
void someMethod(List<MyInterface> items) {
for (MyInterface item : items) {
double value = item.getValue();
long timestamp = item.getTimestamp();
// ...
}
}
If you're not defining the class of these objects, there's no way to enforce it at compile time. Enforcing it at runtime could be possible with elaborate and ugly reflection hacks.
Interfaces can help you regarding your question. You can have separate implementation for each of the following declaration you provide in it.
Cheers. :)
I think you want reflection. You have no control over the kind of objects that may be passed to your code, you just want to be able to check if they comply to your standards. Right? And when they do, you want to be able to call the expected methods.
Search for "Java reflection".
Related
I'm building a sort of framework to avoid repetition of code, and at a certain point I need to convert a list of object Foo into a list of object Bar.
I have database entities that extend
public class BaseEntity {...}
And presentation objects that extend
public class BaseDTO<T extends BaseEntity> {...}
so
public class Foo extends BaseEntity {...}
and
public class Bar extends BaseDTO<A extends BaseEntity> {
public Bar(Foo entity, Locale l) {
...
}
}
Now to convert a list of Foo into a list of Bar is easy using streams
public abstract ClassThatUsesFooAndBar() {
public List<Bar> convertFooToBar(List<Foo> list) {
return list.stream().map(f -> new Bar(f, locale)).collect(...);
}
}
But, and here is the question, these Foo and Bar are actually generics (A and B), so the class that uses Foo and Bar actually is ClassThatUsesAandB<A extends BaseEntity, B extends BaseDTO>, so that function must be abstract too and implemented as boilerplate code with the correct A and B implementations because obviously you cannot instantiate generic types.
Is there a way to use generics/streams/lambdas to create a function that can be written once, so that the implementing classes don't need to re-implement it? The function signature would be
public List<B> convertAToB(List<A> list);
I hope I've been clear enough in what I need, if you need further explanations please ask
Thank you!
I think the simplest way is to use lambdas for the conversion.
public static <A,B> List<B> convertList(List<A> list, Function<A,B> itemConverter) {
return list.stream().map(f -> itemConverter.apply(f)).collect(...);
}
And then you can use it like this:
List<Bar> l = convertList(fooList,foo -> new Bar(foo.getBaz()));
Or if you want to, you can extract it in its own named class:
public class Foo2BarConverter implements Function<Foo,Bar> {
#Override
public Bar apply(Foo f) {
return new Bar(f.getBaz());
}
}
As an aside, given what we can do with streaming, it seems like a bit of a waste to create a new list just to have a materialised list of Bar objects. I would probably chain whatever operation I want to do with the list straight after the conversion.
The most difficult problem with your question is actually not the boilerplate or the streams, it's the generics. Trying to do new B is a bit of a mess. You can't do it directly, and any workaround isn't too clean.
For the boilerplate, however, you can do a bit better thanks to Java 8's default methods in interface. Consider the following interface:
public interface ConversionHandler<A,B> {
B constructB(A a, Locale locale);
default List<B> convertAToB(List<A> list, Locale locale) {
return list.stream().map(a -> constructB(a, locale)).collect(Collectors.toCollection(ArrayList::new));
}
}
The list conversion boilerplate is now done, all you have to do is implement the B construction in the subclass. However, this is still tricky if B is still generic.
public class ClassThatUsesAandB<A, B> implements ConversionHandler<A,B> {
#Override
public B constructB(A a, Locale locale) {
return null; //This is tricky
}
}
However, if the subclass is concrete, it's quite simple
public class ConverterClass implements ConversionHandler<String,Integer> {
#Override
public Integer constructB(String s, Locale locale) {
return s.length();
}
}
So the followup you may want to search for is a good design pattern for making the construction of generic objects as maintainable and readable as possible.
sorry about title since i couldn't find a better one so any edit on that will be appreciated.
consider these classes :
public interface GlobalDashlet {
public Collection<? extends GlobalDashletSetting> getSettings();
public void setSettings(Collection<? extends GlobalDashletSetting> settings);
}
public class Dashlet implements GlobalDashlet {
private Collection<DashletSetting> settings;
public Collection<DashletSetting> getSettings(){
return settings;
}
//This Wont Work
public void setSettings(Collection<DashletSetting> settings) {
this.settings = settings;
}
//This Will Work
public Collection<DashletSetting> getSettings(){
return settings;
}
}
public class DashletSetting implements GlobalDashletSetting {
}
Why overriding the setter method(i mean the way that i have done) wont work (the dashlet class complains about the unimplemented method) but overriding the getter method works?
how can i fix it? i need to be able to implement setter methods too (like the way that i have override the getter methods) because i have to serillize the Dashlet class with jackson mapper and Jackson can not determine the actual type of and object at run time without additional information on super classes.
The reason is that return types may be covariant.
You can always return a more specific type (i.e. a subtype) when overriding a method. A more comprehensible example is the following:
class NumberProvider {
Number getNumber() { return 1.23; }
}
class IntegerProvider extends NumberProvider {
// Returning a more specific type when overriding:
#Override
Integer getNumber() { return 42; }
}
The type Collection<DashletSetting> is a proper subtype of Collection<? extends GlobalDashletSetting>. See the section about Which super-subtype relationships exist among instantiations of generic types? in the Generics FAQ.
For the setter, this does not work. The short reason why it does not work is: It is not type safe. An example of where the type safety is violated is easy to find, although it may seem a bit contrived at the first glance:
// This is the interface as it was defined:
public interface GlobalDashlet {
public void setSettings(Collection<? extends GlobalDashletSetting> settings);
}
public class Dashlet implements GlobalDashlet {
// Assume this was working:
public void setSettings(Collection<DashletSetting> settings) {
// Then you could add a "DashletSetting" here:
settings.add(new DashletSetting());
}
}
// But someone who CALLED this method may not have given it
// a Collection<DashletSetting>, but maybe a collection
// like Collection<SpecialGlobalDashletSetting>:
Collection<SpecialGlobalDashletSetting> settings = ...;
GlobalDashlet dashlet = new Dashlet();
// Based on the method signature that was defined in the interface,
// this would be possible:
dashlet.setSettings(settings);
// Now, the "settings" collection WOULD contain a simple "DashletSetting",
// although it should only contain "SpecialGlobalDashletSetting" instances
// This would cause a ClassCastException sooner or later
The example may look a bit confusing. Again, it's more intuitive with the "simple" types like Number and Integer, but it boils down to the same problem: If a more specific type was allowed for the setter method, then the type safety may be violated.
Because overrided method can not restrict the scope of input variable. Original method can accept anything which extends GlobalDashletSetting class but, but overriden method isrestricting to only one subclass of GlobalDashletSetting class
Because it has different signatures.
Collection<DashletSetting> is not Collection<? extends GlobalDashletSetting>
you need to override the exact signature, not part of it.
if you have method that takes Object, you cant override it with method that takes String even the String extends Object
in youre case, Collection<DashletSetting> and Collection<? extends GlobalDashletSetting> are actually different classes, you have to override with the same class.
the getter is working since it has the same signature (same method name and no params), thats not the case in the setter
In my project I see the interface like this. All the model extend the interface. I am wondering what is the use ?
public interface IModel {
<T> T modelTo(Class<T> clazz);
}
public interface IPerson extends IModel {
public String getFirstName();
public void setFirstName(String firstName);
public String getMiddleName();
public void setMiddleName(String middleName);
}
Then in some places in the code I see like
#Override
public void modelJoin(IModel parent, IModel sample) {
//Some code
IPerson sample= sample.modelTo(IPerson.class);
IPerson person = parent.modelTo(IPerson.class);
//Some code
}
Can you explain me the insight of it ?
It looks like the use of the Adapter pattern. The idea is to create a "view" of a class given another class, or adapt one type of class to act as another.
A simple real world example can be that of electrical sockets. In different countries different types of sockets are used. So you use adapters to plug in your phone into an electrical socket it normally doesn't "recognize".
This can of course be modelled using object oriented programming and the adapter pattern as well. Using your IModel interface but naming it IAdaptable it could be used like this.
public interface IAdaptable {
<T> T adaptAs(Class<T> clazz);
}
public interface IChargeAmerican { void chargePhoneInAmerica(); }
public interface IChargeEurope { void chargePhoneInEurope(); }
public class EuropeanSocket implements IAdaptable, IChargeEurope {
public <T> T adaptAs(Class<T> clazz) {
if (clazz.equals(IChargeAmerican.class)) {
return new EuropeanSocketToAmericanSocketAdapter(this);
}
throw new RuntimeException("unknown");
}
public void chargePhoneInEurope() {
;
}
}
public class AmericanSocket implements IChargeAmerican {
public void chargePhoneInAmerica() {
;
}
}
public class EuropeanSocketToAmericanSocketAdapter implements IChargeAmerican {
private EuropeanSocket socket;
public EuropeanSocketToAmericanSocketAdapter(EuropeanSocket socket) {
this.socket = socket;
}
public void chargePhoneInAmerica() {
socket.chargePhoneInEurope();
}
}
And to use it one would simply adapt the european socket to an american one, sort of like plugging in an adapter in between the two.
public void foo() {
EuropeanSocket europe = new EuropeanSocket();
IChargeAmerican murica = europe.adaptAs(IChargeAmerican.class);
murica.chargePhoneInAmerica();
}
This example shows how the adaptAs method creates a link between the two interfaces IChargeAmerican and IChargeEurope. Even though they don't have anything in common the adapter can act as they do.
Now, the EuropeanSocket implements the IAdaptable interface in order to "convert" itself to another known socket. Usually though the class should not be responsible for this. As the example at wikipedia shows, a factory or provider is better suited for this.
I think that you ask why the method signature
<T> T modelTo(Class<T> clazz);
is used.
The parameter clazz is used to have the type information inside the method implemented. You can then access the type information very easy.
You can then create an object and return it from the implemented method that has the given class.
The method signature looks a bit clumsy but is helpful as the generic information is missing after compilation (type erasure) and the parameters give you the possibility to access the type information (and thereforethe expected return type).
I can imagine it may have been made that way to allow type casting by passing a Class object as a parameter of other methods calling the modelTo(Class clazz) method, or in other words : having other methods casting IModel objects to any class without even knowing which class they will cast it into (nothing even prevents from passing a Class instance to this method which isn't even a subtype of IModel...)
It would be interesting to know how this modelTo method is implemented. Is there a single, final implementation in an abstract skeleton class ? How does it respond to errors (like passing null as the clazz parameter, or triggering a ClassCastException) ? In other words : could this be an attempt to encapsulate all class casts into a single method, to replace ClassCastExceptions with a custom Exception or something like that ? (ClassCastException being a RuntimeException, it could have been a way to make sure a checked exception is thrown instead to enforce explicit exception handling everywhere in the code, I've already seen projects using such an approach...)
I have a method that looks like this
public static <T extends MyClass, X extends AnotherClass> List<T> (Class<T> aParameter, X anotherParameter)
Now if AnotherClass is an abstract class that does NOT Have getId defined, but every single class that extends this interface does. (Don't ask me why it is designed this why, I did not design the abstract class, and I am not allowed to change it).
How can I do something like this
anotherParameter.getId();
I know I have to cast it to the class, but then i have to do an instanceof check for every possible class and then cast it.
So right know i have something like:
if (anotherParameter instanceof SomeClass)
((SomeClass)anotherParameter).getId(); //This looks bad.
Is it possible to cast this dynamically?, to whatever anotherParameter is at runtime?.
Can you modify derived classes? If so, you could define an interface for this (syntax maybe wrong):
public interface WithId {
void getId();
}
...
public class MyDerivedClass1 extends AnotherClass implements WithId {
...
}
...
public class MyDerivedClass2 extends AnotherClass implements WithId {
...
}
and then, inside your method do:
...
if (anotherParameter instanceof WithId) {
WithId withId = (WithId) anotherParameter;
withId.getId();
}
...
If you can change your method's signature, maybe you can specify an intersection type:
public static <T extends MyClass, X extends AnotherClass & WithId> List<T> myMethod(Class<T> aParameter, X anotherParameter)
and then you would have getId() available directly inside your method.
I would say no, since due to type erasure, X is actually just Object at runtime. You could try doing something with reflection to test if anotherParameter has getId() and if so, call it.
You could use reflection to invoke the method at runtime if it exists.
try {
Method m = anotherParameter.getClass().getMethod("getId", null);
Object result = m.invoke(anotherParameter, null);
}
catch (NoSuchMethodException e) {
// ... and several other exceptions need to be caught
}
The concept of casting something at runtime doens't really make sense, as you have an instance, and it can tell you what class it is. You will need to use reflection, for example using the Introspector class.
private Integer getId(final X anotherParameter) {
final BeanInfo beanInfo = Introspector.getBeanInfo(anotherParameter.getClass());
for (MethodDescriptor methodDescriptor : beanInfo.getMethodDescriptors()) {
final Method method = methodDescriptor.getMethod();
if ("getId".equals(method.getName())
&& method.getParameterTypes().length == 0) {
return (Integer) method.invoke(anotherParameter);
}
}
return null;
}
As others here have said, reflection is the only practical solution to this, but I would enhance this a little bit by caching the reflection metadata (perhaps a map keyed by the class+methodName), as that part of reflection isn't completely cheap. You can't help the "invoke()" part.
How can I have an abstract enum, or some kind of base enum?
In my common code I'd like a notion of an enum placeholder, MyItems, without tying myself to a concrete enum. Then in each of my projects I would have a concrete implementation.
E.g.
Common Code
public interface MyItems {
// Marker interface
}
Project A
public enum Items implements MyItems {
RED_CAR, BLUE_CAR, GREEN_CAR;
}
Project B
public enum Items implements MyItems {
BROWN_TREE, GREEN_TREE;
}
This seems to work, but in my common code I can't write a loop over my interface enum, since it's not an enum. In my common code I'd like to write
for (MyItems item : MyItems.values())
doSomething(item);
but I can't because my interface is just a marker interface, and it doesn't have a .values().
Any suggestions greatly appreciated. I don't know if I'm trying in completely the wrong way.
It doesn't really make sense to do this - because the values() method is static. To call it, you need to know the type you want to call it on.
The closest you could come would be to have:
public interface MyItemsFactory<T extends MyItems>
{
Iterable<T> values();
}
and then implement that in some generic way, e.g.
public class EnumFactory<T extends Enum<T> & MyItems>
implements MyItemsFactory<T>
{
private final Class<T> clazz;
public EnumFactory(Class<T> clazz)
{
this.clazz = clazz;
}
public Iterable<T> values()
{
return EnumSet.allOf(clazz);
}
}
But the basic rule is that polymorphism and static methods don't mix. In your call:
for(MyItems item : MyItems.values())
doSomething(item);
which implementation of MyItems would you expect it to iterate over? You could have loads of types implementing MyItems.
You could look into replacing the enums with the Type Safe Enum Pattern, which would allow you to implement an interface, with a values() method that returned all the values for a particular implementation.
Get the class and dig the values with Class.getEnumConstants() from it.