I have an Object Conversion Class that converts from my domain level objects to DTOs.
I effectively have the following structure
class RuleGroupDTO {
List<RuleDTO> ruleDTOs;
// other members
EvaluationRuleDTO and AssignmentRuleDTO both extend from RuleDTO
My API for conversion is as follows:
public RuleGroupDTO convert(RuleGroup ruleGroup);
So when I pass in my domain RuleGroup to the convert class, it looks at a code associated with the RuleGroup and then constructs either EvaluationRuleDTO or AssignmentRuleDTOs encapsulated within the RuleGroupDTO.
When I retrieve back my RuleGroupDTO, I know that it will contain a List<RuleDTO> that is either List<EvaluationRuleDTO> or List<AssignmentRuleDTO>.
However, to get the correct class version I need to loop through the List<RuleDTO> and cast to either List<EvaluationRuleDTO> or List<AssignmentRuleDTO>
This seems messy, and I am thinking that I can leverage some generic concepts to avoid performing this loop + cast.
What would be a possible approach to changing my API or object structure to take advantage of generics here?
If you have a set amount of types and you want them separate, then return a pojo with the various types separated into different collections, e.g.:
public class DTOResult {
public List<EvaluationRuleDTO> evalDTOs;
public List<AssignmentRuleDTO> assignDTOs;
}
Use List<RuleDTO> to avoid casting, and for god's sake don't write a loop. Make RuleDTO implement a visitor pattern that allows any consumer to handle either kind of subclass in a type-safe manner.
Java sucks at variant types.
Related
I have problem with understand why String[] args variable has no forEach method? I can not find any information that this type is not Serializable or Collection because forEach methos implements Serializable.
For example, I have simple main Java class. If I want to use forEach method, I have to first import Arrays class and then on stream use forEach method like below:
import java.util.Arrays;
public class MyClass {
public static void main(String[] args) {
Arrays.stream(args).forEach(System.out::println);
}
}
Why it is not possible to make it just simple like this?
args.forEach(System.out::println);
Short answer: Arrays don't have a forEach method defined on them.
Longer answer: Because it doesn't need it. An array type (using [], not List<>) represents a low level structure in memory, more suited to low level optimisations rather than higher level functional-style code. The hardware of a machine much more closely resembles the imperative, stateful style from languages like C, rather than the functional stateless style from languages like Haskell. Because of this, when creating a lower level data structure like a basic array, it doesn't necessarily make sense to give it more advanced functionality. If you really want a forEach() method, trivially wrap it using Arrays.asList(), Arrays.stream(), or List.of() (depending on Java version).
The main method takes one parameter of type String[]. Which is an Array of Strings.
Lists and Arrays are two different things and only the former does provide a foreach method.
Not just String array, Array of any object or primitive types do not have this feature since arrays are the data stricture that is different from other collection implementations
The direct superclass of an array type is Object.
Every array type implements the interfaces Cloneable and java.io.Serializable.
https://docs.oracle.com/javase/specs/jls/se7/html/jls-10.html
Any array type doesn't define forEach.
Why?
It simply wasn't implemented and the authors apparently want to keep array types as fundamentally pure as possible.
I don't think this method would be superfluous; on the contrary, I am sure it would be very handy. It's not a trivial task, though. Think about primitive arrays and how you would implement, let's say, a boolean consumer. You would have to bound a plain JDK class BooleanConsumer to a fundamental JVM concept boolean[], or to grand the interface a special status, or to generate the interface on the fly.
If I am creating a java class to be generic, such as:
public class Foo<T>
How can one determine internally to that class, what 'T' ended up being?
public ???? Bar()
{
//if its type 1
// do this
//if its type 2
// do this
//if its type 3
// do this
//if its type 4
// do this
}
I've poked around the Java API and played with the Reflection stuff, instanceof, getClass, .class, etc, but I can't seem to make heads or tails of them. I feel like I'm close and just need to combine a number of calls, but keep coming up short.
To be more specific, I am attempting to determine whether the class was instantiated with one of 3 possible types.
I've used a similar solution to what he explains here for a few projects and found it pretty useful.
http://blog.xebia.com/2009/02/07/acessing-generic-types-at-runtime-in-java/
The jist of it is using the following:
public Class returnedClass() {
ParameterizedType parameterizedType = (ParameterizedType)getClass()
.getGenericSuperclass();
return (Class) parameterizedType.getActualTypeArguments()[0];
}
In contrast to .NET Java generics are implemented by a technique called "type erasure".
What this means is that the compiler will use the type information when generating the class files, but not transfer this information to the byte code. If you look at the compiled classes with javap or similar tools, you will find that a List<String> is a simple List (of Object) in the class file, just as it was in pre-Java-5 code.
Code accessing the generic List will be "rewritten" by the compiler to include the casts you would have to write yourself in earlier versions. In effect the following two code fragments are identical from a byte code perspective once the compiler is done with them:
Java 5:
List<String> stringList = new ArrayList<String>();
stringList.add("Hello World");
String hw = stringList.get(0);
Java 1.4 and before:
List stringList = new ArrayList();
stringList.add("Hello World");
String hw = (String)stringList.get(0);
When reading values from a generic class in Java 5 the necessary cast to the declared type parameter is automatically inserted. When inserting, the compiler will check the value you try to put in and abort with an error if it is not a String.
The whole thing was done to keep old libraries and new generified code interoperable without any need to recompile the existing libs. This is a major advantage over the .NET way where generic classes and non-generic ones live side-by-side but cannot be interchanged freely.
Both approaches have their pros and cons, but that's the way it is in Java.
To get back to your original question: You will not be able to get at the type information at runtime, because it simply is not there anymore, once the compiler has done its job. This is surely limiting in some ways and there are some cranky ways around it which are usually based on storing a class-instance somewhere, but this is not a standard feature.
Because of type erasure, there is no way to do this directly. What you could do, though, is pass a Class<T> into the constructor and hold onto it inside your class. Then you can check it against the three possible Class types that you allow.
However, if there are only three possible types, you might want to consider refactoring into an enum instead.
The Problem is that most of the Generic stuff will disappear during compilation.
One common solution is to save the type during the creation of the Object.
For a short introduction in the Type Erasure behaviour of java read this page
If you know a few specific types that are meaningful, you should create subclasses of your generic type with the implementation.
So
public class Foo<T>
public ???? Bar()
{
//else condition goes here
}
And then
public class DateFoo extends Foo<Date>
public ???? Bar()
{
//Whatever you would have put in if(T == Date) would go here.
}
The whole point of a generic class is that you dont need to know the type that is being used....
It looks like what you want is in fact not a Generic class, but an interface with a number of different implementations. But maybe it would become clearer if you stated your actual, concrete goal.
I agree with Visage. Generics is for compile-time validation, not runtime dynamic typing. Sounds like what you need is really just the factory pattern. But if your "do this" isn't instantiation, then a simple Enum will probably work just as well. Like what Michael said, if you have a slightly more concrete example, you'll get better answers.
I described my previous problem here:
Java - how can I loop methods with same name but different parameters
And I have question related to that.
Is given there example - a good example of using wrapper class?
class Wrapper{
Part param1;
File param2;
File param3;
}
class Validator{
void validate (Wrapper wrapper);
}
class ValidatorA extends Validate{
void validate (Wrapper wrapper){
//use wrapper.part...
}
}
class ValidatorC extends Validate{
void validate (Wrapper wrapper){
//use wrapper.file...
}
}
But it makes me wonder. Is wrapper correct name for it? Is is valid wrapper class? From what I read wrapper classes are used for primitives to use them as objects, shouldn't then it be named different? Or am I wrong?
I need it to be called same way, so I can loop over it so overloading is not the answer. Given class works fine - I just think if is it correct way to use wrapper name?
Wrapper is not good choice in this case. Usually wrapper is used to wrap some different things so they look alike even they are totally different. For example you may have some stream of data which comes from different sources - file, http connection, resources. All what you care is to read data from this source. So, you write wrapper which reads from any source and just deliver data.
Wrapper should not be mixed with common functionality. In example above all 3 sources could be treated as stream so natural solution would be use them all as streams. But even eventually inside wrapper they are used as streams they still require different treatment and actions to work with them. And wrapper takes care about it. You do not care what is wrapped wraps - you just use this wrapped thing in common way which wrapper provides.
In your example we have regular object which encapsulates some data and functionality. This is regular OOP approach. Calling it Wrapper only misguide users who may use this code later.
I have a need to have XYZIdentifier object which will be used in composition in other class to identify the object.
However, Depending on the use-case (a variable in the client object), the identifier can be either a String, long, or even a Class.
Something like IntegerIdentifier, StringIdentifier, FooIdentifier and some interface defined which can be generic.
How can I create this design?
Not sure what your full context is, but part of the solution may involve generics to fetch the kind of result you need, like:
public <T extends IdentifierBase> T getIdentifier(Class<T> kindYouWant) { ... }
The idea being you tell it which flavor you need, and it could either convert with best-effort, or return Null if that kind isn's available.
Like I said, not sure of your whole question...
If I am creating a java class to be generic, such as:
public class Foo<T>
How can one determine internally to that class, what 'T' ended up being?
public ???? Bar()
{
//if its type 1
// do this
//if its type 2
// do this
//if its type 3
// do this
//if its type 4
// do this
}
I've poked around the Java API and played with the Reflection stuff, instanceof, getClass, .class, etc, but I can't seem to make heads or tails of them. I feel like I'm close and just need to combine a number of calls, but keep coming up short.
To be more specific, I am attempting to determine whether the class was instantiated with one of 3 possible types.
I've used a similar solution to what he explains here for a few projects and found it pretty useful.
http://blog.xebia.com/2009/02/07/acessing-generic-types-at-runtime-in-java/
The jist of it is using the following:
public Class returnedClass() {
ParameterizedType parameterizedType = (ParameterizedType)getClass()
.getGenericSuperclass();
return (Class) parameterizedType.getActualTypeArguments()[0];
}
In contrast to .NET Java generics are implemented by a technique called "type erasure".
What this means is that the compiler will use the type information when generating the class files, but not transfer this information to the byte code. If you look at the compiled classes with javap or similar tools, you will find that a List<String> is a simple List (of Object) in the class file, just as it was in pre-Java-5 code.
Code accessing the generic List will be "rewritten" by the compiler to include the casts you would have to write yourself in earlier versions. In effect the following two code fragments are identical from a byte code perspective once the compiler is done with them:
Java 5:
List<String> stringList = new ArrayList<String>();
stringList.add("Hello World");
String hw = stringList.get(0);
Java 1.4 and before:
List stringList = new ArrayList();
stringList.add("Hello World");
String hw = (String)stringList.get(0);
When reading values from a generic class in Java 5 the necessary cast to the declared type parameter is automatically inserted. When inserting, the compiler will check the value you try to put in and abort with an error if it is not a String.
The whole thing was done to keep old libraries and new generified code interoperable without any need to recompile the existing libs. This is a major advantage over the .NET way where generic classes and non-generic ones live side-by-side but cannot be interchanged freely.
Both approaches have their pros and cons, but that's the way it is in Java.
To get back to your original question: You will not be able to get at the type information at runtime, because it simply is not there anymore, once the compiler has done its job. This is surely limiting in some ways and there are some cranky ways around it which are usually based on storing a class-instance somewhere, but this is not a standard feature.
Because of type erasure, there is no way to do this directly. What you could do, though, is pass a Class<T> into the constructor and hold onto it inside your class. Then you can check it against the three possible Class types that you allow.
However, if there are only three possible types, you might want to consider refactoring into an enum instead.
The Problem is that most of the Generic stuff will disappear during compilation.
One common solution is to save the type during the creation of the Object.
For a short introduction in the Type Erasure behaviour of java read this page
If you know a few specific types that are meaningful, you should create subclasses of your generic type with the implementation.
So
public class Foo<T>
public ???? Bar()
{
//else condition goes here
}
And then
public class DateFoo extends Foo<Date>
public ???? Bar()
{
//Whatever you would have put in if(T == Date) would go here.
}
The whole point of a generic class is that you dont need to know the type that is being used....
It looks like what you want is in fact not a Generic class, but an interface with a number of different implementations. But maybe it would become clearer if you stated your actual, concrete goal.
I agree with Visage. Generics is for compile-time validation, not runtime dynamic typing. Sounds like what you need is really just the factory pattern. But if your "do this" isn't instantiation, then a simple Enum will probably work just as well. Like what Michael said, if you have a slightly more concrete example, you'll get better answers.