I have some models which implement an interface, i.e. they all implement a specific method, let's call it method "A". Now I have a class with method "B" which is supposed to call method "A". So I defined it so it gets the interface as an input argument, and all is well. The problem is when I give the models (which implement the interface) to method "B", it says the types are different.
I tried casting the models to the interface, it gives me the "incompatible types" error.
Here is what I have:
public interface BaseObject<T> {
boolean isEqualTo(T object); //AKA: method "A"
}
public interface BaseList<T extends BaseObject> {
boolean areListsEqual(List<T> firstList, List<T> secondList); //AKA: method "B"
}
public class Helper implements BaseList<BaseObject> {
#Override
public boolean areListsEqual(List<BaseObject> firstList, List<BaseObject> secondList) {
boolean isEqual = true;
...
for (int i = 0; i < firstList.size(); i++) {
isEqual = isEqual && firstList.get(i).isEqualTo(secondList.get(i));
}
return isEqual;
...
}
}
// I have different ones
public class MyModel implements BaseObject<MyModel>{
...
}
And here's the part which I get the errors:
List<MyModel> first = new ArrayList<>():
List<MyModel> second = new ArrayList<>():
...
new Helper().areListsEqual(first, second);
// This is another thing I tried
new Helper().areListsEqual((List<BaseObject>) first, (List<BaseObject>) second);
So I found a solution. I had to convert the list. I added the method to Helper class and converted each list before giving it to "areListsEqual" method. Here's how it goes:
public List<BaseObject> convertList(List inputList){
List<BaseObject> baseList = new ArrayList<>();
if (inputList != null && inputList.size() > 0)
baseList.addAll(inputList);
return baseList;
}
And this is how I call it:
Helper helper = new Helper();
helper.areListsEqual(helper.convertList(first), helper.convertList(second));
Related
I'm wondering how does lambdas external references work. Let me explain:
Suppose i have this supplier implementation and this model class :
public class TestSupplierImpl implements Supplier<Boolean> {
public Predicate<Integer> predicate;
public TestSupplierModel model;
public TestSupplierImpl() {
this.predicate = i -> model.something.equals(i);
}
#Override
public Boolean get() {
return predicate.test(3);
}
}
class TestSupplierModel {
public Integer something;
public TestSupplierModel(Integer something) {
this.something = something;
}
}
Then i execute the following code:
TestSupplierImpl test = new TestSupplierImpl(); // line 1
test.model = new TestSupplierModel(3); // line 2
Boolean resultado = test.get(); // line 3
Line 1: creating a new instance of TestSupplierImpl. This new instance's predicate has a null reference of model. This makes sense because at the moment of creation of the predicate, model reference is null.
Line 2: assign to variable model a new instance of TestSupplierModel.
Line 3: test.predicate now has model reference with the new assigned value. Why is this ?
I don't understand why ,when I changed model reference, the predicate updates its model reference to the new one. How is that ?
Thanks in advance !
Does it make sense if you rewrote your TestSupplierImpl() constructor as follows?
public Predicate<Integer> predicate;
public TestSupplierModel model;
public TestSupplierImpl() {
// same effect as this.predicate = i -> model.something.equals(i);
this.predicate = new Predicate<Integer>() {
public boolean test(Integer i) {
return model.something.equals(i);
}
};
}
#Override
public Boolean get() {
return predicate.test(3);
}
So here is the order of things.
// the constructor is run and the test method defined BUT NOT executed.
TestSupplierImpl test = new TestSupplierImpl(); // line 1
// Now you define model
test.model = new TestSupplierModel(3); // line 2
// Then you execute the predictate via get()
Boolean resultado = test.get(); // line 3
model and something aren't required until you issue the get() method. By that time they are already defined.
I am trying to implement Iterator design pattern for generic type. I can not use generic array to store collection, Can someone help me to design Iterator pattern for generic types.
My code here:
public class NamesRepository<T> implements Container<T> {
public NamesRepository(){
names = new T[]; // Compilation error
}
public T names[];
#Override
public Iterator<T> getIterator() {
return new NameIterator();
}
private class NameIterator implements Iterator<T>{
private int index;
#Override
public boolean hasNext() {
if(index<names.length)
return true;
return false;
}
#Override
public T next() {
if(this.hasNext())
return names[index++];
return null;
}
}
}
As has been discussed many times before, you can't directly create a generic array using the type parameter. You can follow that question's answers if you must use an array.
However, you can create a List of a type parameter instead. No tricks are necessary, and it's more flexible.
public NamesRepository(){
names = new ArrayList<T>(); // Easy creation
}
public List<T> names;
Then, your iterator's hasNext() method can compare its index to names.size(), and the next() method can return names.get(index++). You can even implement the other method required for the Iterator interface, remove(), by calling names.remove(index).
You cannot create an array of type parameter. Rather you can store an Object[] array, and type cast the element that you are returning to T:
public NamesRepository(){
names = new Object[5]; // You forgot size here
}
public Object names[];
And then change the next() method as:
#Override
public T next() {
if(this.hasNext()) {
#SuppressWarnings("unchecked")
T value = (T)names[index++];
return value;
}
return null;
}
And you can really change the hasNext() method to a single line:
#Override
public boolean hasNext() {
return index < names.length;
}
The function NameRespositary() is wrongly creating a list of generic types. You have to create it through the type parameter.
public NamesRepository(){ names = new ArrayList<T>(); } public List<T> names;
I have multiple classes that all inherit from the same Block class, and want to instantiate one of them based on a variable value.
Here is what I did for now:
public enum MapCases {
FLOOR (Floor.class), // These are all subclass of my Block class
WALL (Wall.class),
ROCK (Rock.class);
private Class<?> blockType;
MapCases (Class<?> pointing) {
this.block = pointing;
}
public Class<?> getType () {
return this.blockType;
}
};
Then later, I try to instantiate them given some data:
private Block[] blocks; // Array of the mother type
...
blocks = new Block[data.length]; // data is an int array
for (int i = 0; i < data.length; i++) {
int choice = data[i];
Class<?> blockType = MapCases.values()[choice].getType();
blocks[i] = new blockType(); // blockType is of unresolved type
}
But Eclipse shows me an error saying it can't resolve blockType to a type (which seems logical given the fact that java don't know yet the type).
How could I achieve what I am trying to do?
You shouldn't need reflection to do this. Consider this instead:
public enum MapCases {
FLOOR {
#Override
public Block makeBlock() {
return new Floor();
}
},
WALL {
#Override
public Block makeBlock() {
return new Wall();
}
},
ROCK {
#Override
public Block makeBlock() {
return new Rock();
}
};
public abstract Block makeBlock();
}
In this case, the enum itself acts as the factory instead of the Class token it was holding.
Note that if you did want to stick with the Class token, it should be typed as Class<? extends Block>, as Elliott Frisch points out in the comments. Then a call to blockType.getConstructor().newInstance(), which GGrec's answer demonstrates, will return an instance of Block.
Use reflection to create a new instance from the class blueprint.
Pattern:
Class.forName(className).getConstructor().newInstance();
Your case:
blocks[i] = blockType.getConstructor().newInstance();
I'm sorry if this question has been asked before, but I don't really know what to search for.
Anyway, I'm making a math package, and many of the classes extend Function:
package CustomMath;
#SuppressWarnings("rawtypes")
public abstract class Function <T extends Function> {
public abstract Function getDerivative();
public abstract String toString();
public abstract Function simplify();
public abstract boolean equals(T comparison);
}
I want to compare functions to see if they're equal. If they're from the same class, I want to use its specific compare method, but if they're of different classes, I want to return false. Here is one of the classes I have currently:
package CustomMath;
public class Product extends Function <Product> {
public Function multiplicand1;
public Function multiplicand2;
public Product(Function multiplicand1, Function multiplicand2)
{
this.multiplicand1 = multiplicand1;
this.multiplicand2 = multiplicand2;
}
public Function getDerivative() {
return new Sum(new Product(multiplicand1, multiplicand2.getDerivative()), new Product(multiplicand2, multiplicand1.getDerivative()));
}
public String toString() {
if(multiplicand1.equals(new RationalLong(-1, 1)))
return String.format("-(%s)", multiplicand2.toString());
return String.format("(%s)*(%s)", multiplicand1.toString(), multiplicand2.toString());
}
public Function simplify() {
multiplicand1 = multiplicand1.simplify();
multiplicand2 = multiplicand2.simplify();
if(multiplicand1.equals(new One()))
return multiplicand2;
if(multiplicand2.equals(new One()))
return multiplicand1;
if(multiplicand1.equals(new Zero()) || multiplicand2.equals(new Zero()))
return new Zero();
if(multiplicand2.equals(new RationalLong(-1, 1))) //if one of the multiplicands is -1, make it first, so that we can print "-" instead of "-1"
{
if(!multiplicand1.equals(new RationalLong(-1, 1))) // if they're both -1, don't bother switching
{
Function temp = multiplicand1;
multiplicand1 = multiplicand2;
multiplicand2 = temp;
}
}
return this;
}
public boolean equals(Product comparison) {
if((multiplicand1.equals(comparison.multiplicand1) && multiplicand2.equals(comparison.multiplicand2)) ||
(multiplicand1.equals(comparison.multiplicand2) && multiplicand2.equals(comparison.multiplicand1)))
return true;
return false;
}
}
How can I do this?
With generic you have the guarantee that the equals method is only apply with the type 'T', in this case 'Product'. You can't passe another class type.
Another possibility would be in classe Function define:
public abstract boolean equals(Function comparison);
And in classe Product the object comparison whith a comparison instanceof Product
Override Object.equals(Object) method. You don't need to use generics here. Its body will look something like this
if (other instanceof Product) {
Product product = (Product) other;
// Do your magic here
}
return false;
I am relatively inexperienced with java & generics, so please excuse me if this is a stupid question.
I have 3 very similar helper methods called verifyTextualSort, verifyNumericSort and verifyDateSort.
The 3 methods follow the same pattern with only a slight difference in them:
private boolean verifyTextualSort(...) {
ArrayList<String> list = new ArrayList<String>();
// Do common stuff with the list
// Do textual-specific stuff
// Do common stuff with the list
}
private boolean verifyNumericSort(...) {
ArrayList<Integer> list = new ArrayList<Integer>();
// Do common stuff with the list
// Do Numeric-specific stuff
// Do common stuff with the list
}
Is there some way I can combine them into one method, passing somehow the type (Integer, String, Date) as a parameter? I have to be able to know which is the type from inside the method so that I can do the correct specific stuff.
You need three method for the specific stuff. However for the common stuff you can create a common method they both call.
private boolean verifyNumericSort(...) {
List<Integer> list = new ArrayList<Integer>();
commonStuff1(list);
// Do Numeric-specific stuff
commonStuff2(list);
}
You could pass a Class as a parameter, if that is what you want (as you said, passing the type as a parameter):
public <T> void test(List<T> l, T t, Class<T> c) {
System.out.println(c.getName());
System.out.println(l.get(0).getClass().getName());
System.out.println(t.getClass().getName());
}
All the sysouts above will print out the name of the class, so you'll be able to choose which one suits you the best.
You can't do that by introspection using the Generics because of type erasure. But if the list is not empty, you can check the type of the first element and then invoke appropriate method.
since you have 3 fields you can do this..
class A
{
private Date date = null;
private Integer int = null;
private String text = null;
//add getters and setters for these fields
}
and now pass this class Object as an arguement to that method
public boolean verify(A a){
a.getDate();
a.getInt()
//etc and do your stuff
}
You need generics and refactoring:
private boolean verifyTextualSort(List<String> strings) {
commonStuffA(strings);
// Do textual-specific stuff
commonStuffB(strings);
return true; // ?
}
private boolean verifyNumericSort(List<Integer> ints) {
commonStuffB(ints);
// Do Numeric-specific stuff
commonStuffB(ints);
return true; // ?
}
private void commonStuffA(List<?> things) { // This method accept a list of anything
// Do common stuff A with the list
}
private void commonStuffB(List<?> things) { // This method accept a list of anything
// Do common stuff B with the list
}
private void someCallingMethod() {
List<String> strings = new ArrayList<String>();
verifyTextualSort(strings);
List<Integer> ints = new ArrayList<Integer>();
verifyTextualSort(ints);
}
I think you could possibly do something similar to this:
public <T extends Object> boolean verify(T t)
{
if(!(t==null))
{
if(t instanceof Date)
{
//Do date verify routine
return true;
}
else if(t instanceof String)
{
//Do String verify routine
return true;
}
else
{
//Do default verify routine which could be Integer
return true;
}
}
return false;
}
NOTE:
This is not tested.
As others have mentioned, you can't do that with generics because of type erasure (see the other answers for a link to type erasure). I believe you can get a reasonable solution (without instanceof) with polymorphism. Here is an example:
public class VerifySort
{
public static void main(String[] args)
{
VerifySort verifySort = new VerifySort();
Date testDate = new Date();
Integer testInteger = 17;
String testString = "Blammy";
verifySort.verify(testString);
verifySort.verify(testInteger);
verifySort.verify(testDate);
}
private boolean verify(Date parameter)
{
SimpleDateFormat dateFormat = new SimpleDateFormat();
System.out.print("Date parameter: ");
System.out.println(dateFormat.format(parameter));
return true;
}
private boolean verify(Integer parameter)
{
System.out.print("Integer parameter: ");
System.out.println(parameter);
return true;
}
private boolean verify(String parameter)
{
System.out.print("String parameter: ");
System.out.println(parameter);
return true;
}