I am seeing the following kind of code repeatedly in Mapreduce programs. This is just a snippet of code taken out. The entire code is available here
what does the super call in the constructor do? Does it call the constructor of IntPair.class? why is such a call necessary.
public static class KeyComparator extends WritableComparator {
protected KeyComparator() {
super(IntPair.class, true);
}
#Override
public int compare(WritableComparable w1, WritableComparable w2) {
IntPair ip1 = (IntPair) w1;
IntPair ip2 = (IntPair) w2;
int cmp = IntPair.compare(ip1.getFirst(), ip2.getFirst());
if (cmp != 0) {
return cmp;
}
return -IntPair.compare(ip1.getSecond(), ip2.getSecond()); //reverse
}
}
super(), when used in the constructor will call the constructor of the class which is extended. In this case, it will call the WriteableComparator constructor. You can see more details on super in the java documentation here:
Java super link
In particular, see the section titled "Subclass Constructors".
Does it call the constructor of IntPair.class?
No, It's just a argument that is passed in the super class constructor.
why is such a call necessary?
To avoid the call of no arguments constructor of the super class that is by default added by the compiler.
If there are multiple constructors in the super class then you can be specified which constructor of the super class should be called based on arguments.
Sample code: (Look at the output when KeyComparator object is created)
class WritableComparator {
public WritableComparator(){
System.out.println("default constructor is called");
}
public WritableComparator(Class<?> clazz, boolean flag) {
System.out.println("two arguemnts constructor is called");
}
}
class KeyComparator extends WritableComparator {
public KeyComparator() {
//super(); // by default added by the compiler
super(IntPair.class, true);
}
}
IntPair.class notation is used to get object describing this class. Like here:
Class<?> type = Integer.class;
This type variable is not an instance of Integer class, but instance of object describing Integer type.
Some classes requires you to pass them type of objects you want them to work with. Then, they can for example create new instances of those classes, using this type object.
more about Class class
Related
I am tasked with creating a predicate interface and implementing a number of classes that implements that interface. For example, a class called StartsWith is to be generic and needs to have a constructor that accepts any object that is a subclass of CharSequence.
Here is what I currently have:
Predicate.java
package predicates;
interface Predicate<T> {
public char StartsWith(T obj);
}
StartsWith.java
package predicates;
public class StartsWith<T extends CharSequence> implements Predicate<T> {
#Override
public char StartsWith(T obj) {
return 'a';
// TODO Auto-generated method stub
}
}
An example of creating a StartsWith object must look like the following:
StartsWith<String> predicate = new StartsWith<String>("aB");
When I try to instantiate an object like this I am immediately met with an error that says the arguments do not match and for me to provide no arguments in order to make it right, however, it MUST be called this way.
I am confused as to what I am doing wrong here.
This
public char StartsWith(T obj) {
//....
... is a method declaration, not a constructor. I'd in fact call it a "pseudo" constructor since it has the same name as a class. Constructors don't have a return type, not void, not anything.
and here:
StartsWith<String> predicate = new StartsWith<String>("aB");
You call it as if it were a constructor, which again, it is most definitely not.
So,...
Don't give your methods the same names as constructors
Learn and use Java naming conventions. Variable names should all begin with a lower letter while class names with an upper case letter. Learning this and following this will allow us to better understand your code, and would allow you to better understand the code of others.
So, for example:
public class FooPredicate {
public static void main(String[] args) {
StartsWith<String> predicate = new StartsWith<String>();
System.out.println(predicate.startsWithMethod("abc"));
}
}
interface Predicate<T> {
public char startsWithMethod(T obj);
}
class StartsWith<T extends CharSequence> implements Predicate<T> {
#Override
public char startsWithMethod(T obj) {
return 'a';
}
}
It is easy to define a method returning the same value as the argument:
class A {
public static void main(String[]args) {
Derived sth = new Derived();
String x = sth.foo("hello");
System.out.println(x);
Derived resultTypeIsKnown = sth.foo(sth); // <==== !!!
System.out.println(""+resultTypeIsKnown);
}
}
class Base {
<T>T foo(T t)
{
return t;
}
}
class Derived extends Base {
}
You see that the compiler knows that although foo() is declared in the Base class, the compiler knows that sth.foo(sth) returns an instance of the Derived class:
Derived derivedRatherThanBase = sth.foo(sth);
How do I declare that the return value is of the same class as the object whose method is called? (In particular, for a method that always returns this?)
Something like:
class Base {
<?ThisClass?> bar() {
return this;
}
}
I can write
<T>T getThis(T t)
{
return (T)this;
}
but x.getThis(x) uses an extra argument and produces a warning.
UPDATE OMG, what they are doing in the "possible duplicate"... But I already have the base class, it's a descendant of Collection. In other words, it is required that class Base extends Collection and knows its class.
And the real life code where I want to know THISCLASS already is very complex.
UPDATE2 As to the XY problem, what I want is:
class MyVerySpecialCollectionBase extends ... {
...
THISCLASS addAll(Collection items) { ... }
}
class MyExtendedVerySpecialCollection extends MyVerySpecialCollectionBase {
...
}
// use:
MyExtendedVerySpecialCollection x =
new MyExtendedVerySpecialCollection(aLotOfArgs)
.addAll(list1)
.addAll(list2);
The proposed solution sounds too complex and even less acceptable than either (1) redefining addAll() in each derived class or (2) making x.addAll(list1).addAll(list2); a separate statement.
I have a following superclass:
class FloatVector {
private List<Float> components;
public FloatVector(List<Float> comps)
{
components = comps;
}
public int getComponentCount(){
return components.size();
}
public float getComponent(int ind){
return components.get(ind);
}
//other methods
}
and I want to extend it to, for example, a 2D vector:
public class FloatVector2D extends FloatVector {
FloatVector2D(float x,float y)
{
List<Float> comps = new ArrayList<>();
comps.add(x);
comps.add(y);
super(comps);
}
}
but the IDE claims, that the superclass constructor must be the first call. There must be a way to implement the required behaviour.
super must be the first call in a constructor (if super is called).
You can simply replace your FloatVector2D constructor body with:
super(Arrays.asList(new Float[]{x,y}));
(and add the necessary imports)
Put super(comps); as first line in your FloatVector2D constructor.
Source: http://docs.oracle.com/javase/tutorial/java/IandI/super.html
"Invocation of a superclass constructor must be the first line in the subclass constructor."
This question already has answers here:
How can a Java class have no no-arg constructor?
(8 answers)
Closed 9 years ago.
In java tutorials,
http://docs.oracle.com/javase/tutorial/java/javaOO/constructors.html
You don't have to provide any constructors for your class, but you must be careful when doing this. The compiler automatically provides a no-argument, default constructor for any class without constructors. This default constructor will call the no-argument constructor of the superclass. In this situation, the compiler will complain if the superclass doesn't have a no-argument constructor so you must verify that it does. If your class has no explicit superclass, then it has an implicit superclass of Object, which does have a no-argument constructor.
Can anyone provide me with an example where is this compile error possible?
class A
{
int a;
A(int a)
{
this.a=a;
}
}
class B extends A
{
B(int a)
{
this.a=a;
}
}
class C
{
public static void main(String args[])
{
B obj=new B(20);
System.out.println("a = "+obj.a);
}
}
Error:Constructor A in class A cannot be applied to given types;
{
^
required: int
found:no arguments
reason: actual and formal argument lists differ in length
class A
{
public A(int n)
{
}
}
class B extends A
{
}
Say you have a Super class
class Super {
// no constructor
// Java compiler will assign a default constructor
// Super () {}
}
and a Child class
class Child extends Super {
public Child() {
//super(); --> this statement will be inserted by default by Java compiler, even though you don't put it in your code
}
}
And If Super is like this
class Super {
Super(int a) {
// Now this is the only constructor Super class has
// Java doesn't insert a default constructor now..
}
}
Child cannot have no argument constructor, because Super doesn't have it anymore
class `Child` {
Child() {
// super();
//this will be error since there is no "no-argument" constructor in Super
}
}
I have read a book and it says I can override a method if it has the same signature. according to the book the signature of a method is Method_Name + Parameters passed.
as per the book, i can override a method which has different return types. Is it actually possible to override a method with different return type in Java? because i have done a some search on the net i found people saying that to override a method the return type should be same as well.
according to the book it also says the java will throw a compile error when we try to overload a method with same method name and parameters but different return types since the signature means only the method name and parameters. If this is true, we should be able to override a method with different return type.
Please help me to understand this. Thanks in advance.
You can return a different type, as long as it's compatible with the return type of the overridden method. Compatible means: it's a subclass, sub-interface, or implementation of the class or interface returned by the overridden method.
And that's logical. If a method returns an Animal, and your derived class returns a Cow, you're not breaking the contract of the superclass method, since a Cow is an Animal. If the derived class returns a Banana, that isn't correct anymore, since a Banana is not an Animal.
Your parent class has made a promise to the outside world. For example, the method:
public Price calculatePrice(Items[] items).
It tells the world to expect a Price.
If you enhance that functionality in your subclass, you still have to keep your parent classes' original promises for it.
You can add overloaded ways of calculating:
public Price calculatePrice(Items[] items, Integer minimumCharge).
You can even improve your parent's promises by using a MORE specific return type:
public AccuratePrice calculatePrice(Items[] items, Integer minimumCharge).
But you must return at least the type that your parent promised.
The same goes for Exceptions in the method declaration too.
Yes, it is possible since Java 5, it is called covariant return type. The return type should be a subcass of super class method return type (primitive types are not allowed). Example
class X implements Cloneable {
#Override
protected X clone() {
try {
return (X) super.clone();
} catch (CloneNotSupportedException e) {
throw new Error(e); // can never happen
}
}
}
Here is an example:
class Base {
public Number test() {
return 0;
}
}
class A extends Base {
public Long test() {
return 1L;
}
}
Your overriden method can have same type or the sub-type of the
original return type which is called as covariant return.
If you change the return type of the overriden method to something else which is not a sub-type of the original type, then you'd get a compile time error.
Yes we can override different return types but they should be subclass.
public class Shape {
public Shape area(Integer i) {
System.out.println("Sape Area");
System.out.println("Integer");
return null;
}
}
package com.oops;
public class Circle extends Shape {
public Circle area(Integer i) {
System.out.println("Circle Area");
System.out.println("int");
return null;
}
}
// Covariant Overriding
public class Parent {
public Parent(){}
String parentName;
public Parent(String parentName){
this.parentName=parentName;
System.out.println(this.parentName);
}
public Parent show(){
return new Parent("Parent");
}
}
public class Child extends Parent{
public Child(){}
String name;
public Child(String name){
this.name=name;
System.out.println(this.name);
}
public Child show(){
return new Child("Child");
}
}
public class Main {
public static void main(String[] args) {
Parent parent=new Child();
parent.show();
Parent parent1=new Parent();
parent1.show();
}
}