Question about the AbstractTableModel class and JTable

E

Edward H. Fabrega

AbstractTableModel is an abstract class. From the SRC code that comes with
JDK1.5.0-RC:

public abstract class AbstractTableModel implements TableModel, Serializable
{
//
// Instance Variables
//

/** List of listeners */
protected EventListenerList list

(snip)**************************************************

In the JTable class, one of the constructors goes like this:

public JTable(final Object[][] rowData, final Object[] columnNames) {
this(new AbstractTableModel() {
public String getColumnName(int column) { return
columnNames[column].toString(); }
public int getRowCount() { return rowData.length; }
public int getColumnCount() { return columnNames.length; }
public Object getValueAt(int row, int col) { return
rowData[row][col]; }
public boolean isCellEditable(int row, int column) { return
true; }
public void setValueAt(Object value, int row, int col) {
rowData[row][col] = value;
fireTableCellUpdated(row, col);
}
});
}

My question is concerning the creation of an instance of AbstractTableModel
in the JTable constructor with new. Isn't this illegal, and shouldn't it
generate a compile error because AbstractTableModel is an abstract class? I
was under the impression that attempting such a thing would cause a compile
error. Obviously I must be mistaken and am in need of some clarification.
 
E

Espen Hatleskog

From API:

To create a concrete TableModel as a subclass of AbstractTableModel you
need only provide implementations for the following three methods:

public int getRowCount();
public int getColumnCount();
public Object getValueAt(int row, int column);

--------

new AbstractTableModel() {
public String getColumnName(int column) { return
columnNames[column].toString(); }
*******************************************************************
public int getRowCount() { return rowData.length; }
public int getColumnCount() { return columnNames.length;}
public Object getValueAt(int row, int col) { return
*******************************************************************
rowData[row][col]; }
public boolean isCellEditable(int row, int column) { return
true; }
public void setValueAt(Object value, int row, int col) {
rowData[row][col] = value;
fireTableCellUpdated(row, col);
}
}

You cannot create an instance of an abstract class, unless you define
(in this case) the methods mentioned above.
AbstractTableModel implements the interface
javax.swing.table.TableModel, therefore you have to define the
implemented interface's methods yourself, overriding the abstract
methods in TableModel.

In cases like JTable's constructor, it is easier to just define the
necessary methods together with the AbstractTableModel than to write a
new class that inherits the AbstractTableModel.

Short example..

This one will not generate a compile error:

new javax.swing.table.AbstractTableModel(){
public int getRowCount() { return 0; }
public int getColumnCount() { return 0; }
public Object getValueAt(int row, int col) { return null; }
};


this one will give you error:

newjavax.swing.table.AbstractTableModel(){
};

So the key is to override abstract methods. Don’t matter where it gets
done, just as long as it gets done.

Hope this gave you some clarification.

regards
Espen Hatleskog
 
P

paul deimos

Edward H. Fabrega said:
AbstractTableModel is an abstract class. From the SRC code that comes with
JDK1.5.0-RC:

public abstract class AbstractTableModel implements TableModel, Serializable
{
//
// Instance Variables
//

/** List of listeners */
protected EventListenerList list

(snip)**************************************************

In the JTable class, one of the constructors goes like this:

public JTable(final Object[][] rowData, final Object[] columnNames) {
this(new AbstractTableModel() {
public String getColumnName(int column) { return
columnNames[column].toString(); }
public int getRowCount() { return rowData.length; }
public int getColumnCount() { return columnNames.length; }
public Object getValueAt(int row, int col) { return
rowData[row][col]; }
public boolean isCellEditable(int row, int column) { return
true; }
public void setValueAt(Object value, int row, int col) {
rowData[row][col] = value;
fireTableCellUpdated(row, col);
}
});
}

My question is concerning the creation of an instance of AbstractTableModel
in the JTable constructor with new. Isn't this illegal, and shouldn't it
generate a compile error because AbstractTableModel is an abstract class? I
was under the impression that attempting such a thing would cause a compile
error. Obviously I must be mistaken and am in need of some clarification.


As long as you override all abstract methods, you can instantiate it.
With
new AbstractTableModel() {..} as one parameter for the constructor of
JTable you make an
anonym inner class. And here
public int getRowCount() { return rowData.length; }
public int getColumnCount() { return columnNames.length; }
public Object getValueAt(int row, int col) { return
you override all abstact methods derived from interface TableModel.
The other functions
public String getColumnName(int column)
public boolean isCellEditable(int row, int column) { return
public void setValueAt(Object value, int row, int col) {
have default-implementations in AbstractTableModel.
 
E

Edward H. Fabrega

You cannot create an instance of an abstract class, unless you define (in
this case) the methods mentioned above.
AbstractTableModel implements the interface javax.swing.table.TableModel,
therefore you have to define the implemented interface's methods yourself,
overriding the abstract methods in TableModel.

In cases like JTable's constructor, it is easier to just define the
necessary methods together with the AbstractTableModel than to write a new
class that inherits the AbstractTableModel.

Short example..

This one will not generate a compile error:

new javax.swing.table.AbstractTableModel(){
public int getRowCount() { return 0; }
public int getColumnCount() { return 0; }
public Object getValueAt(int row, int col) { return null; }
};

Hi, Espen. I'm telling you, this has wracked my world. One of the axiom's of
my knowledge of object oriented programming is that you cannot instantiate
abstract classes ... that they need to be extended with subclasses that
implement the abstract methods of the parent. With C++ there is a similarity
with abstract classes when one of its functions is declared a pure virtual
function. This has got me so shook up that I went to Barnes and Nobles and
rifled through every java book in the place, looking up abstract classes,
looking for where my thinking has been wrong. Cay S. Horstmann himself, on
page 165 of his latest Core Java 2 Fundamentals (seventh edition) states:

"Abstract classes cannot be instantiated. That is, if a class is declared as
abstract, no objects of that class can be instantiated."

This makes absolute sense to me, because it is in keeping with
object-oriented principles. At least a dozen other java books mirrored
Horstmann's proclamation concerning the IMPOSSIBILITY of instantiating
abstract classes. Yet there is the code in the JTable constructor. Later
tonight, when I have time I'll ginni up an abstact class myself and try to
instantiate it with new under various situations and see what happens (with
and without abstract methods, with and without implementing them).

Ed
 
C

Carl Howells

Edward said:
Hi, Espen. I'm telling you, this has wracked my world. One of the axiom's of
my knowledge of object oriented programming is that you cannot instantiate
abstract classes ... that they need to be extended with subclasses that
implement the abstract methods of the parent.

You are correct. Abstract classes cannot be instantiated. The example
you were given is *NOT* instantiating an abstract class. It's
instantiating an anonymous subclass of an abstract class. Check your
java references for information on anonymous classes, as that will
explain what's going on.
 
E

Edward H. Fabrega

Carl Howells said:
You are correct. Abstract classes cannot be instantiated. The example
you were given is *NOT* instantiating an abstract class. It's
instantiating an anonymous subclass of an abstract class. Check your java
references for information on anonymous classes, as that will explain
what's going on.

Thanks for the steerage. All earthquakes have subsided. The syntax would
have made more sense to be: new Class extends AbstractTableModel { }, as
that is what is actually happening. I suppose they wanted to make it
succint.
 
E

Espen Hatleskog

I can understand that you are a bit confused :)

Try looking at it a bit different...

- Here i am actually trying to instantiate a object of the
AbstractTableModel :

new javax.swing.table.AbstractTableModel(); not good..!!

while here:

new javax.swing.table.AbstractTableModel(){
public int getRowCount() { return 0; }
public int getColumnCount() { return 0; }
public Object getValueAt(int row, int col) { return null; }
};

the body of the abstract class gets altered, so it is no longer the
actual abstract class anymore. What you get from the above code is
really an anonymous class that in a way inherits AbstractTableModel.

Hope not to confuse you more, but another example that you might have
used without even thinking about it is when/if you program GUI. Lets say
you need a listener for a button, that just does one simple operation,
it would be overkill to write a new class that implemented the interface
actionListener. Instead you do this:

//remember that ActionListener is interface

btnButton.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
whateverActionYouWant();
}
});
It might look like I am creating an instance of ActionListener.

This offcourse does not try to instantiate an abstract class, but as I
am sure you know, as with abstracts you cant create an instance of an
interface either. So it is really the same thing.

It creates anonymous classes that override the methods in the abstract
classes or interfaces.

Another example:

public abstract class testAbstr {
public testAbstr() {
System.out.println("abstract Test");
}
public abstract void getDrunk();
}

Say you want to create an instance of the above class.

new testAbstr(){public void method(){}}; Works fine.
new testAbstr(); Fails.

The first one works because it returns an object that overrides the
abstract getDrunk() in testAbstr, it is not an object of testAbstr. The
second tries to create an object of testAbstr.

So you can continue to consider abstracts and interfaces as
un-instantiatable. :)

Let me know if anything is unclear...

Regards
Espen Hatleskog
 
E

Edward H. Fabrega

Espen Hatleskog said:
I can understand that you are a bit confused :)

Try looking at it a bit different...

- Here i am actually trying to instantiate a object of the
AbstractTableModel :

new javax.swing.table.AbstractTableModel(); not good..!!

while here:

new javax.swing.table.AbstractTableModel(){
public int getRowCount() { return 0; }
public int getColumnCount() { return 0; }
public Object getValueAt(int row, int col) { return null; }
};

the body of the abstract class gets altered, so it is no longer the actual
abstract class anymore. What you get from the above code is really an
anonymous class that in a way inherits AbstractTableModel.

Hi, Espen. Everything you said makes sense now. It was the syntax that was
getting to me. C++ has no corrollory to inner classes and what was actually
happening with them isn't clear. In my mind, I now look at annonymous inner
classes like this (using AbstractTableModel as an example):

new AbstractTableModel() {methods} is equivalent to: new Class extends
AbstractTableModel {methods }

Now my only remaining question is, if the annonymous class is an extension
of a class that has field data, can that field data be used in the
annonymous class?

example, suppose I instantiated an annonymous class extending a Rectangle
(say that it was a parameter in some other method in some class, like:

someMethod( new Rectangle() {
x = 10; // have acces to the inherited fields like this?
y = 10;
setSize(100, 100);
System.out.print("Rectangle bounds: " + getBounds());
}, int, int);

Why I would want to do something like this escapes me now, but is it
possible?

Thanks for you help.

Ed
 
@

@(none)

Edward said:
Hi, Espen. Everything you said makes sense now. It was the syntax that was
getting to me. C++ has no corrollory to inner classes and what was actually
happening with them isn't clear. In my mind, I now look at annonymous inner
classes like this (using AbstractTableModel as an example):

new AbstractTableModel() {methods} is equivalent to: new Class extends
AbstractTableModel {methods }

Now my only remaining question is, if the annonymous class is an extension
of a class that has field data, can that field data be used in the
annonymous class?

example, suppose I instantiated an annonymous class extending a Rectangle
(say that it was a parameter in some other method in some class, like:

someMethod( new Rectangle() {
x = 10; // have acces to the inherited fields like this?
y = 10;
setSize(100, 100);
System.out.print("Rectangle bounds: " + getBounds());
}, int, int);

Why I would want to do something like this escapes me now, but is it
possible?

Thanks for you help.

Ed

Above code does not seem to be legal code for any class body, you can't
assign or call methods in class body, class body can have only variable
declrations or methods so you can do

someMethod( new Rectangle() {
int scale=2;//define a new variable
int getScaledArea(){
return x*y*scale; //where x and y are declared by Rectangle
}
}, anInt, anOtherInt);


Haroon
 
E

Espen Hatleskog

Edward said:
Now my only remaining question is, if the annonymous class is an extension
of a class that has field data, can that field data be used in the
annonymous class?

Yes. Ill demonstrate it for you with an extention to my previous example:


public abstract class testAbstr {
public String testString = "testString";
public testAbstr() {
System.out.println("jaja,. denne var jo abstract");
}
public abstract void aMethod();
}

Here you see that i have added the field testString. it is easily
accessed i.e. like this:

System.out.println((new testAbstr(){public void aMethod(){}}).testString );

You can see the overriding of aMethod, and after instantiation i
retreive the testString from the anonyme object, declared in the
abstract testAbstr class.


regards

Espen Hatleskog
 
E

Edward H. Fabrega

Espen Hatleskog said:
Yes. Ill demonstrate it for you with an extention to my previous example:


public abstract class testAbstr {
public String testString = "testString";
public testAbstr() {
System.out.println("jaja,. denne var jo abstract");
}
public abstract void aMethod();
}

Here you see that i have added the field testString. it is easily accessed
i.e. like this:

System.out.println((new testAbstr(){public void
aMethod(){}}).testString );

You can see the overriding of aMethod, and after instantiation i retreive
the testString from the anonyme object, declared in the abstract testAbstr
class.


regards

Espen Hatleskog

Thanks for your information and example. This technique might be useful in
helping to debug a problem exists in an annonymous class.

Ed
 
T

Tor Iver Wilhelmsen

Edward H. Fabrega said:
someMethod( new Rectangle() {
x = 10; // have acces to the inherited fields like this?
y = 10;
setSize(100, 100);
System.out.print("Rectangle bounds: " + getBounds());
}, int, int);

You need to place initialization code in anonymous classes in an
initializer block:

someMethod( new Rectangle() {
{
x = 10; // have acces to the inherited fields like this?
y = 10;
setSize(100, 100);
System.out.print("Rectangle bounds: " + getBounds());
}
}, int, int);
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top