Mit Anmerkungen, um sicherzustellen, dass der Rückgabewert der Methode wird nicht verworfen

String in Java unveränderlich ist. Der folgende Codeausschnitt ist, grob gesagt, "falsch".

String s = "hello world!";

s.toUpperCase(); //"wrong"!!

System.out.println(s); //still "hello world!"!!!

Obwohl dies "falsch" ist, wird der code kompiliert und ausgeführt wird, vielleicht, um die Verwirrung der viele Anfänger, die muss entweder gesagt werden, was der Fehler ist, oder für sich selbst heraus finden, indem wir die Dokumentation.

Lesen der Dokumentation ist ein wesentlicher Teil des Verstehens eine API, aber ich Frage mich, ob dies kann ergänzt werden durch zusätzliche compile-Zeit überprüft. Insbesondere Frage ich mich, ob vielleicht die Java-annotation framework kann verwendet werden, um zu erzwingen, dass der Wert, der zurückgegeben wird, indem Sie bestimmte Methoden nicht ignoriert werden. API-Designer/Bibliothek-Autoren wäre, dann verwenden Sie diese Anmerkung in Ihre Methoden zu dokumentieren, die Werte zurückgeben, sollten Sie nicht ignoriert werden.

Sobald die API wird ergänzt mit dieser annotation (oder vielleicht ein anderer Mechanismus), dann, wenn ein Benutzer schreibt einen code wie oben, es würde nicht kompiliert (oder so tun, mit eine ernste Warnung).

So kann dies getan werden, und wie würden Sie gehen über das tun so etwas?


Anhang: Die Motivation

Scheint es klar, dass im Allgemeinen Fall, Java sollte ermöglichen, Rückgabewerte von Methoden, um ignoriert zu werden. Die Rückgabewerte von Methoden wie Liste.add (immer true), System.setProperty (vorherigen Wert), kann wohl getrost ignoriert werden die meisten der Zeit.

Allerdings gibt es auch viele Methoden, deren Rückgabewerte sollten NICHT ignoriert werden. Dabei ist fast immer ein Programmierer Fehler, oder sonst nicht ordnungsgemäße Verwendung der API. Diese beinhaltet Dinge wie:

  • Methoden auf unveränderliche Typen (z.B. String, BigInteger, etc), die Rückkehr der Ergebnis von Operationen statt mutierend der Instanz aufgerufen wird.
  • Methoden, deren Rückgabewert ist ein wichtiger Teil seines Verhaltens und sollte nicht ignoriert werden, aber manche Leute tun es trotzdem (z.B. InputStream.read(byte[]) gibt die Anzahl der bytes gelesen, welche sollte NICHT davon ausgegangen, dass die gesamte Länge des array)

Derzeit können wir schreiben codes ignoriert, dass diese Werte zurückgeben und Sie kompilieren und ausführen, ohne Warnung. Statische Analyse-Steine - /bug-Finder/Stil Vollstrecker/etc. kann fast sicher Kennzeichnen Sie diese als möglich, code smells, aber es scheint angemessen zu sein/ideal, wenn dies durchgesetzt werden kann, die von der API selbst, vielleicht durch Anmerkungen.

Ist es fast unmöglich für eine Klasse, um sicherzustellen, dass es wird immer dann verwendet, "richtig", aber es gibt Dinge, die Sie tun können, um zu helfen, Kunden auf die richtige Nutzung an (siehe: Effektive Java 2nd Edition, Item 58: Verwenden Sie überprüft die Ausnahmen für die erzielbaren Konditionen und Laufzeit-exceptions für Fehler in der Programmierung und Punkt 62: Dokumentieren Sie alle Ausnahmen, die durch jede Methode). Eine Anmerkung, die durchsetzen würde Kunden nicht ignorieren Rückgabewerte von bestimmten Methoden ist, und es wird verstärkt durch den compiler zur compile-time entweder in form von Fehlern oder Warnungen, scheint im Einklang mit dieser Idee.


Anhang 2: Snippet

Das folgende ist eine vorläufige Versuch, kurz und bündig zeigt, was ich erreichen möchte:

@interface Undiscardable { }
//attachable to methods to indicate that its
//return value must not be discarded

public class UndiscardableTest {
     public static @Undiscardable int f() {
             return 42;
     }

     public static void main(String[] args) {
             f(); //what do I have to do so this generates
                  //compilation warning/error?

             System.out.println(f()); //this one would be fine!
     }
}

Der obige code kompiliert und läuft einwandfrei (wie gesehen auf ideone.com). Wie kann ich es machen das es nicht so? Wie kann ich das zuweisen der Semantik möchte ich @Undiscardable?

  • OK, ich habe gerade untersuchte, ein wenig über @Nullable/NotNull annotation, und das scheint Recht ähnlich zu sein im Geist mit dem, was ich tun will, also das muss machbar sein: jetbrains.com/idea/documentation/howto.html ("IntelliJ IDEA warnt Sie, wenn diese Verträge verletzt werden.")
  • Dieser link kann hilfreich sein: JDT-APT für Eclipse, mit tutorials eclipse.org/jdt/apt/index.html
  • Undiscardable ist eine schlechte Namenswahl. Diese Methoden Idempotent sind. Zusätzlich zu Ihrem Undiscardable check, der compiler könnte optimiert werden einige for-Schleifen, wenn Sie wüsste, welche Methoden wurden idempotent.
  • InputStream.read ist nicht idempotent. Dies ist nicht wirklich über compiler-Optimierung, aber, wie Sie schreiben, benutzerfreundliche API.
  • es ist ein Fall für verwerfen einige InputStream.Lesen. wenn u r interessiert nur die letzten bytes des Streams, u haben, um noch zu Lesen der ersten bytes. Wenn Sie keine Verwendung der ersten bytes, warum nicht werfen Sie?
  • InputStream.read(byte[]) nicht immer füllen des Puffers. Sie muß nicht verwerfen, ist der zurückgegebene Wert, der Ihnen sagt, wie viele bytes wurden tatsächlich gelesen.

Schreibe einen Kommentar