Blog
Skip to end of metadata
Go to start of metadata

Az eddigi legjobb dolog - ami a Java nyelvvel történt - az annotációk bevezetése volt. Egy csomó keretrendszer alapul annotációkon, mint a JPA, a Seam vagy a Spring 2.5, de a fejlesztők jó része még nem készített saját annotációt. A The Wrong Code blog írója első blogbejegyzésében rögtön egy kisregényt írt az annotációkról, mégpedig a saját készítésű annotációkról. A programozók népe ugyanis alapvetően lusta (ezért lettek programozók), így amíg nem muszáj, nem használnak újabb technológiákat, mert azt meg kell tanulni. Nézzük a blogban említett példát, amely egy fotó reprezentációja:

Photo.java
public class Photo
{
  private long id;
  private String contentType;
  private String caption;
  private byte[] data;

  @Override
  public String toString()
  {
    return String.format("Photo(id=%d,caption=%s,contentType=%s)",id, caption, contentType);
  }
}

Az @Override annotációval talán mindenki találkozott, a lényege, hogy egy ilyenformán jelölt metódusnak felül kell definiálnia egy azonos nevű és tulajdonságú metódust az ősosztályban. Ez elsőre feleslegesnek tűnhet, azonban nagyobb rendszerek esetén sokszor előfordul, hogy változik az API és az implementációt megvalósító osztályokban pedig benne maradnak olyan források, amelyek eredetileg felüldefiniáltak egy ősosztálybeli metódust, amit viszont eltüntettek a tervezők. Tűzzük ki feladatnak, hogy egy annotációval jelezzük a toString metódusunknak: az adott attribútumot írja ki, ha az osztály példányát valamilyen (naplózási, hibakeresési, stb.) okból kiíratnánk.

PartOfStringRepresentation.java
@Retention(RetentionPolicy.RUNTIME)
public @interface PartOfStringRepresentation
{
}

public class Photo
{
  @PartOfStringRepresentation
  private long id;

  @PartOfStringRepresentation
  private String caption;

  @PartOfStringRepresentation
  private String contentType;

  private byte[] data;

  @Override
  public String toString()
  {
    try
    {
      StringBuilder builder = new StringBuilder();
      builder.append(getClass().getSimpleName());
      builder.append('(');
      Field[] declaredFields = getClass().getDeclaredFields();
      boolean firstField = true;
      for (int i = 0; i < declaredFields.length; ++i)
      {
        Field declaredField = declaredFields[i];
        if (declaredField.getAnnotation(PartOfToStringRepresentation.class) != null)
        {
          if (firstField)
          {
            firstField = false;
          } else
          {
            builder.append(", ");
          }
          builder.append(fieldName);
          builder.append('=');
          builder.append(fieldValue);
        }
      }
      builder.append(')');
      return builder.toString();
    } catch (IllegalAccessException e)
    {
      throw new RuntimeException(e);
    }
  }
}

Első ránézésre erőteljesen összetett lett a toString metódusunk, viszont észre kell venni, hogy mindez a nagy kódbázis kiszervezhető egy külön osztályba, s ezek után már csak az annotáció dönti el, hogy egy attribútum része lesz-e a kiírásnak vagy sem. Több tucat entitás esetén már biztos megéri használni, használjuk.

      
      
Page viewed times

4 Comments

  1. Auth Gábor AUTHOR

    Ti szoktatok ilyen egyedi annotációkat készíteni? Mert én például nem... :)
    1. Egyelőre nekem sem volt még alkalmam saját annotációkat csinálni, de itt egy keretrendszer, ami masszívan használja őket. Ilyen scaffolding-szerű dolgot csinál. Megadod az osztály mezőire hogy melyik kötelező, melyik string milyen értékeket vehet fel (regex) stb és ez alapján legyárt valami GUI-t.
    2. Unknown User (kuvera)

      Én több saját annotációt írtam már, nagyon hasznos dolog. Példa: tetszőleges entitásból JSP űrlap automatikus legyártása. Az űrlapon adatmezőnként kell a megnevezés címke és az űrlapmező típusa (text, select, checkbox)

      @ViewDef(formCaption="Lista neve")
      String viewname;
      
      @ViewDef(formCaption="Kategória", type="-listcateg")
      int categid;
      
      @ViewDef(formCaption="Sorszám")
      int ordering;
      @ViewDef(formCaption="Hierarchia", type="/")
      boolean hierarchy;

      A JSP generátor kap egy entitást, és az annotációkből kigyűjt olyan adatot, aminek közvetett köze van csak az entitás működéséhez. A type="/" checkboxot gyárt, a "-" kezdetű pedig select listát, aminek tartalmára a string utal.

      1. Auth Gábor AUTHOR

        Úgy igazából a hír alapjául szolgáló írás után döbbentem rá, hogy igen nagy - kihasználatlan - erőtartalékok vannak még a Java nyelvben. Ha mindenki rászokna a generics és az annotations használatára, akkor igen ütős dolgokat lehetne művelni, egyszerűen annotáció alapú keretrendszerek kiadásával. Értve itt például kuvera írását... :)