I'm trying to define an abstract class that takes in a List of things and does stuff. Something like:
abstract public class AbstractClass {
private final List<?> list;
public AbstractClass(List<?> list) {
this.list = list;
}
public List<?> getList() { return list; }
abstract void addToList(List<?> list);
}
public class Class1 extends AbstractClass {
public Class1(List<Integer> list) {
super(list);
}
#Override
void addToList(List<Integer> list) {
// do stuff
}
}
public class Class2 extends AbstractClass {
public Class2(List<String> list) {
super(list);
}
#Override
void addToList(List<String> list) {
// do stuff
}
}
List<Integer> a = new List<Integer>();
Class1 c1 = new Class1(a);
List<Integer> b = c1.getList();
c1.addToList(a);
List<String> c = new List<String>();
Class2 c2 = new Class2(c);
List<Integer> d = c2.getList();
c2.addToList(c);
Having addToList with specific types in the subclasses is generating errors, but I don't know if that's a matter of syntax (with my poor knowledge of generics) or what I'm trying to do itself (is it possible to overload an abstract method like that)?
You should make AbstractClass a typed class instead of using the ? wildcard.
abstract public class AbstractClass<T> {
private final List<T> list;
public AbstractClass(List<T> list) {
this.list = list;
}
public List<T> getList() { return list; }
abstract void addToList(List<T> list);
}
In this case, you would have
public class Class1 extends AbstractClass<Integer> { ... }
public class Class2 extends AbstractClass<String> { ... }
Related
How to add a generic object to list in java?
Currently, I have two classes doing the same function and would like to integrate them together
public class MyClass1 {
private List<Object1> myList = new ArrayList<>();
public void addList(Object1 o) {
myList.add(o);
}
}
public class MyClass2 {
private List<Object2> myList = new ArrayList<>();
public void addList(Object2 o) {
myList.add(o);
}
}
something like
public class MyClass {
private List<Object> myList = new ArrayList<>();
public void addList(Object o) {
myList.add(o);
}
}
You could make your own class generic:
public class MyClass<T> {
private List<T> myList = new ArrayList<>();
public void addList(T o) {
myList.add(o);
}
}
You can make both classes Object1 and Object2 implement the same interface 'ObjInterface'
public class MyClass {
private List<ObjInterface> myList = new ArrayList<>();
public void addList(ObjInterface o) {
myList.add(o);
}
}
If you want the class to contain only Object1 or only Object2 and never anything else, you can combine the other two answers:
interface ObjInterface {
// may be empty
}
public class MyClass<T extends ObjInterface> {
private List<T> myList = new ArrayList<>();
public void addList(T o) {
myList.add(o);
}
}
MyClass<Object1> object1only = new MyClass<>();
MyClass<Object2> object2only = new MyClass<>();
and add implements ObjInterface to the definitions of Object1 and Object2.
If you add methods common to both classes to ObjInterface, you can call those methods on the T objects in MyClass, since they're guaranteed to be a subclass of ObjInterface.
I have these classes:
class Parent {
public Parent() {
}
}
class ChildA extends Parent {
public ChildA() {
super();
}
}
class ChildB extends Parent {
public ChildB() {
super();
}
}
public ListClas(List(Parent) list) {
this.list=list;
}
}
And I want to run ListClas constructor as below.
List<ChildA> list_childA = new ArrayList<ChildA>();
List<ChildB> list_childB = new ArrayList<ChildB>();
ListClas listClasA = new ListClas(list_childA);
ListClas listClasB = new ListClas(list_childB);
But the compiler throws an error. How do I do this correctly using polymorphism?
If you want a function that accepts List containing subclasses of a superclass you should use syntax.
public ListClas(List<? extends Parent> list){
this.list=list;
}
It will accept both of them.
ListClas listClasA = new ListClas(list_childA);
ListClas listClasB = new ListClas(list_childB);
If you change to List<? extends Parent> list (also change ListClas.list field definition) in your ListClas then it will compile and work.
All of them: List<Parent>, List<ChildA> and List<ChildB> are different concrete parameterized type.
You can read more about this here: https://stackoverflow.com/a/20940807/516167
I think you want your ListClas to look something like this:
class ListClas<T>
{
private List<T> list;
public ListClas(List<T> list)
{
this.list = list;
}
}
Then to create them:
ListClas<ChildA> listClasA = new ListClas<ChildA>(list_childA);
ListClas<ChildB> listClasB = new ListClas<ChildB>(list_childB);
The T is a generic type designation. It allows you to use the same class for multiple runtime types. So you can do the above instead of having to write this:
class AListClas
{
private List<ChildA> list;
public AListClas(List<ChildA> list)
{
this.list = list;
}
}
class BListClas
{
private List<ChildB> list;
public BListClas(List<ChildB> list)
{
this.list = list;
}
}
If you don't need quite as much flexibility you could write your ListClas like this:
class ListClas
{
private List<? extends Parent> list;
public ListClas(List<? extends Parent> list)
{
this.list = list;
}
}
and use it like this:
ListClas listClasA = new ListClas(list_childA);
ListClas listClasB = new ListClas(list_childB);
Let's assume I have a class A that can be extended. Within that Class A I have a List List<A>. So this class will contain a list with elements A. Now If I subclass this class B extends A, I want class B to have the same member List<B>, ie the same list but this type containing items of type B. Is this possible using generics ? I can see something like A <T extends A>, while declaring List<T>, but I don't like as the information about the class type are already there. Is there another better solution ? Example below:
public class A {
List<A> list = new ArrayList<A>();
}
public class B extends A {
}
I want list to have the generic type of B in class B.
If you want to put the behaviour in the super class, then you're going to have to tell the super class what type of class the subclass is. This can be done by adding a generic type to the super.
public class A<E> {
protected List<E> items;
public A() {
this.items = new ArrayList<E>();
}
}
public class B extends A<B> {
public static void main(String[] args) {
B b = new B();
b.items.add(b);
}
}
You can use extends keyword in generic.
For example:
public class A {
protected List<? extends A> list;
public A() {
list = new ArrayList<A>();
}
public <T extends A> List<T> getList() {
return (List<T>) list;
}
public void setList(List<A> list) {
this.list = list;
}
}
public class B extends A {
public B() {
list = new ArrayList<B>();
}
public static void main(String[] args) {
A a = new A();
a.getList().add(new A());
B b = new B();
b.getList().add(new B());
}
}
I'm working in a Genetic Algorithm and I want it as abstract as possible to be able to reuse the GA. I defined and implemented a Population Interface, and well it works, but I'm sure that's not the best way to do it. I don't have great experience with Java Generics. Is there an easier way of defining and implementing the Population interface (e.g. maybe avoid a cast conversion? avoid a new list in getChromosomes() ?)
public interface Population
{
void addChromosomes(List<? extends Chromosome> chromosomes);
List<Chromosome> getChromosomes();
// More code here ...
}
public class TSPPopulation implements Population
{
private List<TSPChromosome> chromosomes;
#Override
public void addChromosomes(List<? extends Chromosome> chromosomes) {
for (Chromosome chromosome : chromosomes) {
this.chromosomes.add((TSPChromosome) chromosome);
}
}
#Override
public List<Chromosome> getChromosomes() {
List<Chromosome> newList = new ArrayList<Chromosome>();
for (TSPChromosome chromosome : chromosomes) {
newList.add(chromosome);
}
return newList;
}
}
Use a Bounded Wildcard in your interface:
public interface Population<T extends Chromosome>{
void addChromosomes(List<T> chromosomes);
List<T> getChromosomes();
}
public class TSPPopulation implements Population<TSPChromosome>
{
private List<TSPChromosome> chromosomes;
#Override
public void addChromosomes(List<TSPChromosome> chromosomes) {
...
}
#Override
public List<TSPChromosome> getChromosomes() {
...
}
}
The simplest solution is extending a list (then use addAll(...) to add a list of Chromosoms to the list):
class Population<T extends Chromosome> extends ArrayList<T> {
}
But if you want the same structure I would make Population into a generic list class. That way both add... and get... methods can be handled in the generic base class. If you do want to override any other feature you just extend Population (class TSPPopulation extends Population<TSPChromosome>.
Usage:
public static void main(String... args) {
Population<TSPChromosome> tspPopulation = new Population<TSPChromosome>();
...
}
Implementation:
class Population<T extends Chromosome> {
private List<T> chromosomes = new ArrayList<T>();
public void addChromosomes(List<T> chromosomes) {
this.chromosomes.addAll(chromosomes);
}
public List<T> getChromosomes() {
return new ArrayList<T>(this.chromosomes);
}
}
It would be much safer if you made the Population generic itself:
public interface Population<T extends Chromosome> {
void addChromosomes(List<T> chromosomes);
List<T> getChromosomes();
}
public class TspPopulation implements Population<TspChromosome>{
#Override
public void addChromosomes(List<TspChromosome> chromosomes){
//
}
#Override
public List<TspChromosome> getChromosomes(){
//
}
}
That way you would not need any casting in client code.
I know GAs, and I would question whether your Population implementation actually needs to know which kind of Chromosome you put in. Do you really have different Population implementations depending on the Chromosome subclass? Or what you really want is to make sure you have the same subclass of Chromosome in a Population? In this last case, you can define the Population interface as others suggested, and the make a generic implementation (or skip the interface altogether):
public class PopulationImpl implements Population<T extends Chromosome> {
private List<T> chromosomes;
#Override
public void addChromosomes(List<T> chromosomes) {
this.chromosomes.addAll(chromosomes);
}
#Override
public List<T> getChromosomes() {
return new ArrayList<T>(chromosomes);
}
}
Be careful not to put too many generics, or you will end up with generics hell, or tons of casts which will make generics more annoying than useful.
Yes, for instance:
public interface Population<T extends Chromosome>
{
void addChromosomes(List<T> chromosomes);
List<T> getChromosomes();
// More code here ...
}
public class TSPPopulation implements Population<TSPChromosome>
{
private List<TSPChromosome> chromosomes;
#Override
public void addChromosomes(List<TSPChromosome> chromosomes) {
this.chromosomes.addAll(chromosomes);
}
#Override
public List<TSPChromosome> getChromosomes() {
return new ArrayList<TSPChromosome>(chromosomes);
}
}
I've build the following case. An interface for all JAXBLists:
public interface JaxbList<T> {
public abstract List<T> getList();
}
And an base implementation:
#XmlRootElement(name="list")
public class JaxbBaseList<T> implements JaxbList<T>{
protected List<T> list;
public JaxbBaseList(){}
public JaxbBaseList(List<T> list){
this.list=list;
}
#XmlElement(name="item" )
public List<T> getList(){
return list;
}
}
As well as an implementation for a list of URIs:
#XmlRootElement(name="uris")
public class JaxbUriList2 extends JaxbBaseList<String> {
public JaxbUriList2() { super(); }
public JaxbUriList2(List<String> list){
super(list);
}
#Override
#XmlElement(name="uri")
public List<String> getList() {
return list;
}
}
And I'm using the List in the following way:
public JaxbList<String> init(#QueryParam("amount") int amount){
List<String> entityList = new Vector<String>();
...
enityList.add("http://uri");
...
return new JaxbUriList2(entityList);
}
I thought the output should be:
<uris>
<uri>
http://uri
</uri>
...
</uris>
But it is something like this:
<uris>
<item xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema" xsi:type="xs:string">
http://uri
</item>
...
<uri>
http://uri
</uri>
...
</uris>
I think it has something to do with the inheritance, but I don't get it...
What's the problem? - How can I fix it?
Thanks in advance!
Annotations are obtained through reflection. The annotation is bound to the type it's defined in.
public class AnnotationTest {
public static class A
{
#XmlElement(name="item")
public void doIt() { }
}
public static class B extends A
{
#XmlElement(name="name")
public void doIt() { }
}
public static void main(String[] args)
{
B b = new B();
Method m = b.getClass().getMethods()[0];
Annotation[] ann = m.getDeclaredAnnotations();
System.out.println( ann.length ); // prints 1
}
}
So this behavior is not due to the reflection mechanism itself. It seems like the JAXB framework does explicitly list the annotation on the method in the class and the super classes. Surprisingly this still works, but not as you would like.
Can't you just remove #XmlElement(name="item") in the base class?
EDIT
According to your comment (but still not sure if I understand all correctly), I would suggest:
#XmlRootElement(name="list")
public class JaxbBaseList<T> implements JaxbList<T>{
protected List<T> list;
public List<T> getList(){
return list;
}
}
public class JaxbPrimitiveList<T> extends JaxbList<T>{
protected List<T> list;
#XmlElement( name="item" )
public List<T> getList(){
return list;
}
}
#XmlSeeAlso( Uri )
public class JaxbUriList<Uri> extends JaxbList<Uri>{
protected List<Uri> list;
#XmlElement( name="uri" )
public List<Uri> getList(){
return list;
}
}