I have a question, I'm learning java with a Book, and as I've copied some code in there (and made some changes) and made some investigations, I noticed something odd..., here is the code
public static void main(String[] args)
{
Timer timer = new Timer(1000, (event) ->
{
System.out.println("At the Tone, the time is" + Instant.ofEpochMilli(event.getWhen()));
Toolkit.getDefaultToolkit().beep();
});
timer.start();
JOptionPane.showMessageDialog(null, "Quit?");
System.exit(0);
}
It's just a code that notifies you if a second passes. (this code compiles and runs smoothly)
as you can see Timer Constructor requires 2 pars (int, ActionListener)
public Timer(int delay, ActionListener listener)
and the ActionListener Interface has one method that is actionPerformed and requires ActionEvent parameter
public void actionPerformed(ActionEvent e);
Now here is my question, when calling this actionPerformed Method in that lambda expression above How does the compiler know which constructor to call to instantiate ActionEvent without feeding him any clues about the parameters, ActionEvent has no "No argument Constructor" and the method getWhen() is not static (obj must be instantiated)
Here are all the constructors of ActionEvent:
public ActionEvent(Object source, int id, String command)
public ActionEvent(Object source, int id, String command, int modifiers)
public ActionEvent(Object source, int id, String command, long when,
int modifiers)
I really hope I made myself clear!, Thank you
The compiler does not know! ;-)
It is the Timer
instance that will create the ActionEvent
instance at runtime every delay
and the Timer
instance will call the ActionListener
method actionPerformed
with the ActionEvent
it created.
You can have a look at one of the implementation here:
http://developer.classpath.org/doc/javax/swing/Timer-source.html
/**
* Fire the action event, named "Timer" and having the numeric
* identifier, equal to the numer of events that have been
* already fired before.
*/
void fireActionPerformed()
{
fireActionPerformed(new ActionEvent(this, ticks++, "Timer"));
}
If we look at the source code of javax.swing.Timer
, we note that all the ActionListeners of the Timer
are stored on a javax.swing.event.EventListenerList
, called listenerList
. They are called in this line(s):
fireActionPerformed(new ActionEvent(Timer.this, 0, getActionCommand(),
System.currentTimeMillis(),
0));
With fireActionPerformed:
protected void fireActionPerformed(ActionEvent e) {
// Guaranteed to return a non-null array
Object[] listeners = listenerList.getListenerList();
// Process the listeners last to first, notifying
// those that are interested in this event
for (int i=listeners.length-2; i>=0; i-=2) {
if (listeners[i]==ActionListener.class) {
((ActionListener)listeners[i+1]).actionPerformed(e);
}
}
}
The regular constructor selection process applies.
The Timer
constructor just receives a listener and registers it in its listeners list. When the timer ticks (where listener should be called), the Timer
instance creates a new ActionEvent (See Timer.java:245
) and passes it over to the registered listeners.
So simply saying, the compiler doesn't create it for you. Instead Timer
class does.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.