Why list of String has no forEach method? - java

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.

Related

Inmutable instances/functional interfaces in Java

Is there any way to force an instance or a functional interface static method output to be inmutable in a fashion like Collections.immutable(x)?
I'd like for instance to create sort of Comparator functional interface and disallow chained operations like ".thenComparing()" for some of the static builder-like methods created instances.
You can force your return value to be immutable by returning an instance of an immutable class. There is no general purpose way to make instances of your class immutable without knowing what the class does.
The second paragraph of your question contains an incorrect assumption that .thenComparing(...) makes a comparator mutable. thenComparing leaves the original comparator intact and makes a new comparator.
Sadly, the Java collection types lack immutable collections, but google guava comes with lots of immutable collections (see https://code.google.com/p/guava-libraries/wiki/ImmutableCollectionsExplained), so you can use those as a return type.
Yet, I can't see how this correlates with the ability to compare something, since comparing doesn't change stuff.

Why Java does not allow to extend array type

As an experiment, I tried to extend an int-array like this:
public class IntArrayExtension extends int[]{
// additional fields and methods.
}
to add some methods related to sorting, swapping, sub-array building etc. in the class itself. But I got this error while compiling:
IntArrayExtension.java:1: unexpected type
found : int[]
required: class
public class IntArrayExtension extends int[]{
^
1 error
I am curious to know: why Java does not allow to extend an array?
Extending a fundamental type such as a String or an array opens up security holes. If Java let you extend an array, its methods that take arrays would become insecure. That is why strings are final, and arrays cannot be extended at all.
For example, you could override the clone() method, and return an array of incorrect size. This has a potential of breaking the logic of system code that takes an array as its parameter.
On top of that, arrays are special objects in Java, in that they do not have a class definition.
There are two solution to the problem that you are trying to solve:
You could put the logic into a helper class with static methods, similar to Collections, etc. or
You could encapsulate an array inside your IntArrayExtension class, and provide wrapper methods for accessing the array and its additional features.
Arrays are objects but an array type is not a class and therefore can't be extended. See for example JLS #10.8.

Using generics to avoid looping and casting

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.

How to restrict elements of an ArrayList without using generics

Suppose I have an Employee class. How can I implement an ArrayList only containing Employee elements without using generics? That is, without Arraylist<Employee>, how can I restrict the ArrayList to add only Employee objects?
Extend ArrayList and customize add() and addAll() method to check the object being added is instanceof Employee
You could use a wrapper class that holds a private ArrayList field, say called employeeList, has a
public void add(Employee employee) {
employeeList.add(employee);
}
as well as any other necessary methods that would allow outside classes to interact with the ArrayList in a controlled fashion.
I find it much better to use composition for this than inheritance. That way if you wanted to change from an ArrayList to something else, say a LinkedList, or even something completely different, you would have an easier time.
You could use Collections.checkedList() - but why would you want to not use generics?
Subclass the ArrayList class and name it something like EmployeeArrayList.
If you're wanting to avoid generics for their own sake, e.g. for compatibility with very old versions of Java, then extending or wrapping ArrayList won't help - you probably want to find or make another array implementation that has the same functionality.
Basically, ArrayList is just a wrapper for a primitive array that copies and pastes its data into a larger array when necessary, so this isn't especially difficult to write from scratch.
What exactly do you want when you "restrict"? There are two possible places where one could place a restriction: at compile-time or runtime.
Generics is a purely compile-time thing. It helps you write correct code but you can still bypass it and put the wrong type in the array and it won't complain at runtime.
On the other hand, something like Collections.checkedList()is a runtime restrictions. It throws an error at runtime when an object of the wrong type comes. But it does not help you at compile-time if you do not have generics.
So the two things are orthogonal, and neither is a replacement for the other. What exactly do you want?

Java - Is it possible to subclass an array? And more questions about arrays in Java

These questions are purely asked out of curiosity. I don't actually need to subclass an array, I'm just trying to figure out more about how they work in Java.
Where is the Javadoc API for arrays? I found one for the 'Arrays' class, but that class just contains utilities to use on Java arrays, and is not the actual array class. This leads me to my next question:
IS there an actual array class of which all arrays are subclasses?
Is Object[] a superclass of String[] (for example)? I'm guessing the answer here is no. Are these actual classes like any other class?
Is String[] a different class from String[][]? Or String[][][], etc?
As asked in the title, is it possible to subclass an array class (or to subclass THE array class? still not sure how it works as you can tell by my above questioning)? Could I create my own class, instances of which acted exactly like arrays, except they had more functionality?
Thanks.
The Java Language Specification answers all these questions:
The direct superclass of an array type is Object.
Every array type implements the interfaces Cloneable and java.io.Serializable.
So no, there isn't a common base class for all arrays, and therefore no JavaDoc either. The members of arrays are defined by the spec instead.
Subtyping among array types is defined in section 4.10.3 - and yes, String[] is a subtype of Object[]. See also ArrayStoreException.
Yes, String[].class != String[][].class. (c.f. section 10.8)
No, there is no syntax to subclass arrays. In particular, the extends clause must contain a class type (and array types are not class types).
There is no array class in Java.
Interestingly, arrays are objects (but not class instances):
An object is a class instance or an array.
More here: http://docs.oracle.com/javase/specs/jls/se7/html/jls-10.html
The classes implementing java.util.List provide a more object-oriented implementation of array-like structures.
You can't subclass arrays. Even though the syntax used with them is a bit different, they are objects (check with the JLS). There's not much API to them - apart from just what Object has (with toString() not doing what you expect, use Arrays.deepToString() for that; equals() and hashCode() are similar) there's the length field. Additionally, arrays are cloneable. You can only cast array types if the target element type is a supertype of the source element type - you can cast String[] to Object[] but not the other way around. If you are sure the objects in the array are a specific type, you can cast each element individually. String[][] is an array of String[], so it's a different type than String[] as its elements are arrays of String, not Strings. You can create classes which give similar functionality to arrays (ArrayList does just that), but they will not be interchangeable with regular arrays.

Categories

Resources