Search code examples
javagenericsjavac

What to do about "unchecked call to generic class?"


I have this class:

package Main;

public abstract class Click123<T extends java.awt.Component>  ////////////////
{

  boolean debugging = false;

  public abstract void singleClick(java.awt.event.MouseEvent e); ////////////////
  public abstract void doubleClick(java.awt.event.MouseEvent e); ////////////////
  public abstract void tripleClick(java.awt.event.MouseEvent e); ////////////////
  public abstract void manyClick(java.awt.event.MouseEvent e);   ////////////////
  public abstract int  getFreq();// how long thread sleeps; i.e., click interval

  public Click123(T target)  ////////////////
  {
    target.addMouseListener  ////////////////
    (
      new java.awt.event.MouseAdapter()   ////////////////
      {
        Thread cp = null;

        public void mouseClicked(final java.awt.event.MouseEvent e) 
        {
          if (cp != null && cp.isAlive())
            cp.interrupt(); 

          if (e.getClickCount() == 1) 
          {
            cp =  new Thread(new ClickProcessor(new java.util.concurrent.Callable<Void>() {
              @Override public Void call() throws Exception {
                singleClick(e); //////////////////////////////////////////
                return null;
              }
            }));
            cp.start();
          }
          else if (e.getClickCount() == 2) 
          {
            cp = new Thread(new ClickProcessor(new java.util.concurrent.Callable<Void>() {
              @Override public Void call() throws Exception {
                doubleClick(e); //////////////////////////////////////////
                return null;
              }
            }));
            cp.start();
          }
          else if (e.getClickCount() == 3) 
          {
            cp =  new Thread(new ClickProcessor(new java.util.concurrent.Callable<Void>() 
            {
              @Override public Void call() throws Exception {
                tripleClick(e); //////////////////////////////////////////
                return null;
              }
              })              
            );
            cp.start();
          }
          else manyClick(e); //////////////////////////////////////////
        } // mouseClicked
      }  // new MouseAdapter
    ); // add mouseListener
  } // Click123  

  class ClickProcessor implements Runnable 
  {
    java.util.concurrent.Callable<Void> eventProcessor;

    ClickProcessor(java.util.concurrent.Callable<Void> eventProcessor) 
    {
        this.eventProcessor = eventProcessor;
    }

    @Override public void run() 
    {
      try 
      {
        System.out.println("About to sleep " + getFreq());
          Thread.sleep(getFreq()); // this value comes from implementation
          eventProcessor.call();
      } catch (InterruptedException e) { System.out.println(e);} 
        catch (Exception e)            { System.out.println(e);}
    }  // run
  }  // class ClickProcessor
} // class Click123

The only warning I get from Netbeans is about the "package visible inner class" ClickProcessor.

I compiled my project using this command line:

javac -Xlint:unchecked -classpath main\*.java gbl\*.java

It gave warnings about "unchecked call to Click123<T> as a member of raw type Click123" in several places, including the reference to it in this class:

public class GridCell extends JTextField {

  int     row,
          col;
  char    content;
  Color   foreground,
          background;

  GridCell(){
    content = ' ';
    foreground = Color.BLACK;
    background = Color.WHITE;

    disableKeyCombo(KeyEvent.VK_A, KeyEvent.VK_C, KeyEvent.VK_V, KeyEvent.VK_X,
                                                                 KeyEvent.VK_H);

    new Click123(this) ////////// flagged warning unchecked call to Click123
    {
      @Override
      public void singleClick(MouseEvent e) {
        if(SwingUtilities.isRightMouseButton(e))
        {
          if( ! Game.getAvailable().contains("*"))
            Game.changeSMBorder(e.getComponent().getX(),
                                e.getComponent().getY());
          else
            Game.changeSbBackground(e.getComponent().getX(),
                                    e.getComponent().getY());
        }
        Game.btnClearBorders.setEnabled(true);
      }

      @Override public void doubleClick(MouseEvent e){
        if(SwingUtilities.isRightMouseButton(e))
        {
          if(btnUndo.isEnabled())
            btnUndo.doClick();
        }
      }

      @Override
      public void tripleClick(MouseEvent e) {
        if(SwingUtilities.isRightMouseButton(e))
        {
          if(btnRedo.isEnabled())
            btnRedo.doClick();
        }
      }

      @Override
      public void manyClick(MouseEvent e) {
      }

      @Override
      public int getFreq() {
        return CLICK_FREQUENCY;
      }
    };    
  }
  ... class goes on much further
}

What, if anything, can/should I do?


Solution

  • Try changing

    new Click123(this)
    

    to

    new Click123<GridCell>(this)
    

    Click123 is a generic class which means it has a type parameter, written between angular brackets. For Click123 the type parameter T must be a subclass of Component, which GridCell is.

    Using a raw type like List or Set should be avoided. A raw type is a generic type that is used without type parameters. When generics were introduced, raw types were only allowed for compatibility with code written before generics.

    However, looking at your class it looks like there is no reason why Click123 should be generic at all. Couldn't the constructor just take a Component rather than a T?