今天看到了一种非常奇怪的接口声明:
package org.jetbrains.annotations;// Imports
import java.lang.annotation.Annotation;public abstract @ interface NotNull extends Annotation {  // Methods
  String documentation();
}
在使用的时候,这个接口也非常奇怪,他出现在变量声明的最前端,就像这样:    /**
     * The parent frame for help windows.
     * @serial
     */
    @NotNull
    private final JFrame helpParent;
也出现在参数里:    /**
     * Creates the tile path panel.
     * @param mapTilePane the map tile pane contents
     * @return the tile path panel
     */
    @NotNull
    private static Component createTilePathPanel(@NotNull final Component mapTilePane) {
        final Container panel = new JPanel(new BorderLayout());
        panel.add(mapTilePane, BorderLayout.NORTH);
        return panel;
    }
我听说@NotNull这种用法是J2EE里的,可这个项目是个J2SE项目啊!
哪位高人给解释一下为什么这样用啊?这样用有什么好处?

解决方案 »

  1.   

    另外,里面还有很多@ActionMethod这种写法,跟@NotNull一样,都出现杂方法声明的前面,这是什么呀?
      

  2.   

    楼主,这是JAVA注解,哪都可以用
    public abstract @ interface NotNull extends Annotation {  // Methods
      String documentation();
    }
    这是申明注解
      

  3.   

    不对吧?我知道@是注解,比如@Overwrite这种类型,但是这个接口的声明中出现@怎么解释?意思是说NotNull这个接口只是注解?
      

  4.   

    .......楼主,这就是java自定义注解的申明方式,你说的@Overwrite是JAVA的基本内置注解,JAVA规定了注解就用@interface这种方式来申明,就好像JAVA规定了不允许多重继承,你能和它对着干部
      

  5.   

    意思就是说这实际不是接口,就是声明了一个QNotNull的注释?
      

  6.   


    既然不方便,那我就直接在这里提问吧!public interface MapArchObject<A extends MapArchObject<A>> extends Cloneable, Serializable {    /**
         * Reset the state of this object to the state of the given map arch
         * object.
         * @param mapArchObject the map arch object to copy the state from
         */
        void setState(A mapArchObject);    /**
         * Set map size.
         * @param mapSize new map size
         * @xxx this does not change the size of the underlying MapModel. We
         * eventually should change that so a map size isn't stored twice.
         */
        void setMapSize(Size2D mapSize);    /**
         * Get the map size.
         * @return size of the map reflected by this MapArchObject
         */    Size2D getMapSize();    /**
         * Get the map name.
         * @return map name
         */    String getMapName();    /**
         * Set the map name.
         * @param name new map name
         */
        void setMapName(String name);    /**
         * Get enter x coordinate.
         * @return enter x coordinate.
         */
        int getEnterX();    /**
         * Set enter x coordinate.
         * @param enterX new enter x coordinate
         */
        void setEnterX(int enterX);    /**
         * Get enter y coordinate.
         * @return enter y coordinate.
         */
        int getEnterY();    /**
         * Set enter y coordinate.
         * @param enterY new enter y coordinate
         */
        void setEnterY(int enterY);    /**
         * Returns the enter coordinates.
         * @return the enter coordinates
         */    Point getEnter();    /**
         * Return whether the map is an "outdoor" map.
         * @return Whether the map is an "outdoor" map.
         */
        boolean isOutdoor();    /**
         * Set whether the map is an "outdoor" map.
         * @param outdoor Whether the map is an "outdoor" map.
         */
        void setOutdoor(boolean outdoor);    /**
         * Get the reset timeout (in seconds).
         * @return reset timeout (in seconds).
         */
        int getResetTimeout();    /**
         * Set the reset timeout (in seconds).
         * @param resetTimeout new reset timeout (in seconds)
         */
        void setResetTimeout(int resetTimeout);    /**
         * Get the swap time (in ticks).
         * @return swap time (in ticks).
         */
        int getSwapTime();    /**
         * Set the swap time (in ticks).
         * @param swapTime (in ticks)
         */
        void setSwapTime(int swapTime);    /**
         * Get the map's difficulty.
         * @return map's difficulty.
         */
        int getDifficulty();    /**
         * Set the map's difficulty.
         * @param difficulty new difficulty for this map
         */
        void setDifficulty(int difficulty);    /**
         * Get whether this map uses a fixed reset.
         * @return whether this map uses a fixed reset.
         */
        boolean isFixedReset();    /**
         * Set whether this map uses a fixed reset.
         * @param fixedReset whether this map should use a fixed reset
         */
        void setFixedReset(boolean fixedReset);    /**
         * Get the light / darkness of this map. (0 means fully bright)
         * @return light / darkness of this map
         */
        int getDarkness();    /**
         * Set the light / darkness of this map.
         * @param darkness new light / darkness of this map
         */
        void setDarkness(int darkness);    /**
         * Return the number of tile paths.
         * @return The number of tile paths.
         */
        int getTilePaths();    /**
         * Return a tile path.
         * @param direction The tile path direction.
         * @return The tile path.
         */    String getTilePath(Direction direction);    /**
         * Set a tile path.
         * @param direction The tile path direction.
         * @param tilePath The new tile path.
         */
        void setTilePath(Direction direction, String tilePath);    /**
         * Create a copy of this object.
         * @return Newly created clone of this object.
         */    A clone();    /**
         * Register an event listener.
         * @param listener MapArchObjectListener to register
         */
        void addMapArchObjectListener(MapArchObjectListener listener);    /**
         * Unregister an event listener.
         * @param listener MapArchObjectListener to unregister
         */
        void removeMapArchObjectListener(MapArchObjectListener listener);    /**
         * Start a new transaction. Transactions may be nested. Transactions serve
         * the purpose of firing events to the views when more changes are known to
         * come before the view is really required to update. Each invocation of
         * this function requires its own invocation of {@link #endTransaction()}.
         * <p/> Beginning a nested transaction is a cheap operation.
         * @see #endTransaction()
         * @see #endTransaction(boolean)
         */
        void beginTransaction();    /**
         * End a transaction. Invoking this method will reduce the transaction depth
         * by only 1. <p/> Ending a nested operation is a cheap operation. Ending a
         * transaction without changes also is a cheap operation. <p/> If the last
         * transaction is ended, the changes are committed. <p/> Same as {@link
         * #endTransaction(boolean) endTransaction(false)}.
         * @see #beginTransaction()
         * @see #endTransaction(boolean)
         */
        void endTransaction();    /**
         * End a transaction. Invoking this method will reduce the transaction depth
         * by only 1. <p/> Ending a nested operation is a cheap operation. Ending a
         * transaction without changes also is a cheap operation. <p/> If the last
         * transaction is ended, the changes are committed. <p/> An example where
         * setting <var>fireEvent</var> to <code>true</code> is useful even though
         * the outermost transaction is not ended is when during painting the UI
         * should be updated though painting is not finished.
         * @param fireEvent <code>true</code> if an event should be fired even in
         * case this doesn't end the outermost transaction.
         * @note If the outermost transaction is ended, <var>fireEvent</var> is
         * ignored and the event is always fired.
         * @note An event is never fired when there were no changes, no matter
         * whether the outermost transaction is ended or <var>fireEvent</var> is set
         * to <code>true</code>.
         * @note If the event is fired, the internal change list is not cleared.
         * @see #beginTransaction()
         * @see #endTransaction()
         */
        void endTransaction(boolean fireEvent);    /**
         * Append 'text' to the map text.
         * @param text string to add
         */
        void addText(String text);    /**
         * Set map text.
         * @param text the new map text
         */
        void setText(String text);    /**
         * Returns the message text.
         * @return The message text.
         */    String getText();    /**
         * Updates the "Modified:" attribute in the message text.
         * @param userName the user name to include
         */
        void updateModifiedAttribute(String userName);    /**
         * Check whether the given coordinate is within map bounds.
         * @param pos the coordinates to check
         * @return <code>true</code> if the given coordinates are on the map,
         *         otherwise <code>false</code> (also returns <code>false</code> if
         *         <code><var>pos</var> == null</code>)
         */
        boolean isPointValid(Point pos);    /**
         * Discards map squares that are out of map bounds.
         * @param mapSquares the map squares to check
         */
        <G extends GameObject<G, A, R>, R extends Archetype<G, A, R>> void discardInvalidMapSquares(Collection<MapSquare<G, A, R>> mapSquares);    /**
         * Discards game objects that are out of map bounds.
         * @param gameObjects the game objects to check
         */
        <G extends GameObject<G, A, R>, R extends Archetype<G, A, R>> void discardInvalidGameObjects(Collection<G> gameObjects);} // interface MapArchObject以上这段代码中,MapArchObject<A extends MapArchObject<A>>中的A这个类型标识,是不是可以由我随意指定,比如指定成X、M等等,只要保证不会有重复就行?
      

  7.   

    还有像这个写法<G extends GameObject<G, A, R>, R extends Archetype<G, A, R>> void discardInvalidMapSquares(Collection<MapSquare<G, A, R>> mapSquares)
    既然是void没有返回值的,前面写<G extends GameObject<G, A, R>, R extends Archetype<G, A, R>> 这段是啥意思?
      

  8.   


    <G extends GameObject<G, A, R>, R extends Archetype<G, A, R>> void discardInvalidMapSquares(Collection<MapSquare<G, A, R>> mapSquares)
    <G extends GameObject<G, A, R>, R extends Archetype<G, A, R>> 表明这个方法里要用到G和R类型的变量,貌似是这意思,期待大牛来解释清楚点
      

  9.   

    这个G、A和R是自己随意指定的吗?跟java中的T以及java.util.Hashtable<K,V>中的K、V不一样吗?
      

  10.   

    额,我上面说的不对,楼主去看下这篇文章,应该能理解点
    http://zddava.javaeye.com/blog/375950
      

  11.   


    看了,他的例子举得非常通用,很容易就能看明白。不过对于关键字的使用,他依然用的是系统常见的,比如E(element)、K(key)、V(value);如果我不想使用系统提供的这些类型关键字,而是使用G、A、R这种自定义的关键字,那么是不是就得像前面这样写了?