von Java nach C++



  • @Soller Das wird doch erst richtig lustig wenn man 3 Dateien auf einmal öffnet. 😉
    https://ideone.com/qF5lnZ



  • idx schrieb:

    Na, das ist so alles nicht ganz richtig - ich denke der Grund warum viele C Entwickler Java verabscheuen ist, dass es wirklich mal schlecht und langsam war, aber das ist definitv vorbei.

    Trotzdem, ein Java-Programm wird nie an die Schnelligkeit eines C-Programms rankommen.

    idx schrieb:

    Man benötigt eine JVM das stimmt, dafür hat man halt Platformunabhängigkeit ohne auch nur eine Zeile Code zu ändern oder gar neu kompilieren zu müssen mit den Nachteilen der Sicherheit. Das Browser Plugin muss man nicht installieren, mach ich auch nicht, weil Pulgins nix im Browser zu suchen haben (vor allem Flash nicht)

    Du hast recht, mit dem Flash-Plugin verhält es sich ähnlich. Aber es gibt jetzt HTML5, das hoffentlich dieses Flash-Zeugs überflüssig macht.
    Zurück zur JVM: Es wird häufig behauptet, dass Java plattformunabhängig sei. Das ist schon richtig, aber man muss eben daran denken, WARUM und WIE diese Plattforumunabhängigkeit entsteht. Java-Quellcode wird mit einem eigenen Compiler in ein eigenes Bytecode-Format übersetzt. Dieses Bytecodeformat wird von der JVM interpretiert, und genau hier ist die plattformunabhängigkeit. Die JVM muss für jede erdenkliche Plattform umgemodelt und neu geschrieben werden, d.h. irgendein Programmierer bei Oracle schuftet hart, dass die JVM auf der Zielplattform läuft. Mit dem Ziel: nicht du als Java-Programmierer kümmerst dich um die Plattformumabhängigkeit, sondern irgendein C- oder C++-Programmierer bei Orace. Das Problem namens "Plattformunabhängigkeit" wird also nur verlagert.

    idx schrieb:

    Es ist halt die Quelloffene Version - ursprünglich noch von Sun als OpenSource freigegeben. Ist mittlerweile Standard in fast jeder Linux Distribution

    Es ist aber bei fast keiner vorinstalliert, und das ist auch gut so. Ein Großteil der Linux-Programme sind stinknormale, native Programme, die mit dem GCC direkt von C-Quelltext kompiliert werden.

    idx schrieb:

    Seit Java 1.5 generiert der JIT zur Laufzeit Maschinencode. Langsam ist Java eigentlich nur <= 1.4

    Wie gesagt, ein natives Programm ist IMMER schneller als ein Java-Programm. Egal wie gut oder schnell der Interpreter ist.

    P.S.: Kommt das nur mir so vor, oder ist das Zitiersystem dieses Forums irgendwie lästig?



  • Soller schrieb:

    Ich weiß das Java einem ne Menge abnimmt, auch an Freiheiten, deswegen ist es aber noch lange nicht Müll.

    Das ist ja wohl der Witz des Jahrhunderts.
    Es ist nämlich gerade umgekehrt.

    Wo man mit Java mit try-catch-finaly herumfrickeln darf, weil der tolle GC zwar den Speicher aufräumt den Speicher aufräumt, sonst aber nichts.
    Lässt man unter C++ einfach die Destruktoren für sich arbeiten ( Stichwort RAII)

    PrintWriter file;
    try {
      file = new PrintWriter("Hallo.txt");
      file.println("Hallo Welt!");
    } catch(Exception e) {
    } finally {
      file.close();
    }
    

    Viel kürzer gehts in C++

    std::ofstream file("Hallo.txt");
     file << "Hallo Welt!\n";
    

    Watt hat der GC denn mit nem try catch zu tun das musst du mir mal erklären 🙂

    try catch finally gibts auch in c++ und sollte in kritischen Teilen auch verwendet werden.
    Was ist passiert in deinem Beispiel, wenn es nicht möglich ist Hallo.txt zu erzeugen, oder wenn keine Berechtigung besteht oder was auch immer? Der Code müsste dir um die Ohren fliegen oder was?
    Was ist mit ofstream muss er nicht geschlossen werden oder geflushd, passiert das automatisch?

    Das ist kein gebashe, sondert ernst gemeint, mich würde interessieren, was da passiert.



  • Lerne C++! Komme wieder in 5 Jahren.



  • knivil schrieb:

    Lerne C++! Komme wieder in 5 Jahren.

    Oh, ersteres hatte ich vor, deswegen hatte ich mich hier angemeldet.
    Warum soll ich jetzt wieder gehen?

    Mal davon abgesehen dass ich diesen Thread mit einer einfach Frage ohne gebashe gestartet habe wurde nur auf mich eingeprügelt, weil ich das Wort Java erwähnt habe - was soll das? Seid ihr alle als fertige unantastbare Meister vom Himmel gefallen.

    Habe mir grad das C++ Primer Buch bestellt ich bin schon sehr gespannt wie C++ so ist; vielleicht werde ich ja auch noch nen richtig Fan, aber ich werde deswegen niemals andere nieder machen oder sagen dass sie sich verpissen sollen, nur weil das Wort Java oder PHP oder sonst was erwähnt wird.



  • Soller schrieb:

    Wo man mit Java mit try-catch-finaly herumfrickeln darf, weil der tolle GC zwar den Speicher aufräumt den Speicher aufräumt, sonst aber nichts.
    Lässt man unter C++ einfach die Destruktoren für sich arbeiten ( Stichwort RAII)

    PrintWriter file;
    try {
      file = new PrintWriter("Hallo.txt");
      file.println("Hallo Welt!");
    } catch(Exception e) {
    } finally {
      file.close();
    }
    

    Viel kürzer gehts in C++

    std::ofstream file("Hallo.txt");
     file << "Hallo Welt!\n";
    

    Ab Java 7 gibt es ein "try with resources", in dem einen das Schließen der Resourcen auch abgenommen wird.

    Dein Beispiel sollte da dann ungefähr so aussehen:

    try (PrintWriter file = new PrintWriter("Hallo.txt")){
       file.println("Hallo Welt!");
    }
    


  • cooky451 schrieb:

    @Soller Das wird doch erst richtig lustig wenn man 3 Dateien auf einmal öffnet. 😉
    https://ideone.com/qF5lnZ

    Ja, ne ist klar.

    public class JavaApplication1 {
    
        /**
         * @param args the command line arguments
         */
        public static void main(String[] args) {
            try(PrintWriter file1 = new PrintWriter("file1.txt");
                PrintWriter file2 = new PrintWriter("file2.txt");
                PrintWriter file3 = new PrintWriter("file3.txt")    ) {
            } catch (Exception ex) {            
            }
        }
    }
    


  • Und man braucht dann kein close() mehr?



  • cooky451 schrieb:

    Und man braucht dann kein close() mehr?

    Yup, und wie Gregor schon verlinkt hat:

    http://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html schrieb:

    The try-with-resources statement is a try statement that declares one or more resources. A resource is an object that must be closed after the program is finished with it. The try-with-resources statement ensures that each resource is closed at the end of the statement. Any object that implements java.lang.AutoCloseable, which includes all objects which implement java.io.Closeable, can be used as a resource.



  • Ab Java 7 gibt es ein "try with resources", in dem einen das Schließen der Resourcen auch abgenommen wird

    Richtig!
    Aber Java kann es erst seit Version 7, währen RAII jeder popelige C++ Compiler der letzten 30 Jahre beherrscht.



  • Wenn so ein C++ vs. Java Flamewar auftaucht, schaue ich manchmal im Language Shootout, wie es inzwischen bei der dortigen willkürlichen Wahl von Microbenchmarks aussieht:

    http://benchmarksgame.alioth.debian.org/u64q/benchmark.php?test=all&lang=gpp&lang2=java&data=u64q

    Um es kurz zusammenzufassen:

    1. Bei den benötigten Codezeilen scheinen sich die beiden Sprachen nicht besonders stark zu unterscheiden.

    2. C++ Programme sind typischerweise etwas schneller als Javaprogramme, in der Testmenge an Programmen auf der Seite geht das von einem Faktor 1.0 bis zu einem Faktor 2,4.

    3. Javaprogramme benötigen deutlich mehr Speicher. Das ist vielleicht der größte Nachteil von Java.



  • Zeus schrieb:

    cooky451 schrieb:

    @Soller Das wird doch erst richtig lustig wenn man 3 Dateien auf einmal öffnet. 😉
    https://ideone.com/qF5lnZ

    Ja, ne ist klar.

    public class JavaApplication1 {
    
        /**
         * @param args the command line arguments
         */
        public static void main(String[] args) {
            try(PrintWriter file1 = new PrintWriter("file1.txt");
                PrintWriter file2 = new PrintWriter("file2.txt");
                PrintWriter file3 = new PrintWriter("file3.txt")    ) {
            } catch (Exception ex) {            
            }
        }
    }
    

    Hallo, warum verwendest du das "@" in "@param"?
    Diesen Comment-Style habe ich schon öfters gesehen. Wie heißt das genau?



  • -Nachfrage- schrieb:

    Hallo, warum verwendest du das "@" in "@param"?
    Diesen Comment-Style habe ich schon öfters gesehen. Wie heißt das genau?

    Das sind Javadoc-Kommentare. Javadoc ist ein Werkzeug, das Dir aus solchen Kommentaren eine hübsche html-Doku baut. ...ähnlich wie zum Beispiel Doxygen.



  • Gregor schrieb:

    -Nachfrage- schrieb:

    Hallo, warum verwendest du das "@" in "@param"?
    Diesen Comment-Style habe ich schon öfters gesehen. Wie heißt das genau?

    Das sind Javadoc-Kommentare. Javadoc ist ein Werkzeug, das Dir aus solchen Kommentaren eine hübsche html-Doku baut. ...ähnlich wie zum Beispiel Doxygen.

    Ok, meinst du, es ist sinnvoll, schon von anfang an so seinen Quelltext zu kommentieren, damit man später mit Doxygen eine Doku bauen kann?



  • -Nachfrage- schrieb:

    Ok, meinst du, es ist sinnvoll, schon von anfang an so seinen Quelltext zu kommentieren, damit man später mit Doxygen eine Doku bauen kann?

    Dokumentieren von Anfang an ist immer sinnvoll. Tools zur Erstellung einer HTML-Dokumentation wie Doxygen oder JavaDoc bauen zusätzlich noch Konstrukte, welche schnellere Übersichten für Strukturen und Objekte liefern. Solche "Helferlein" schaffen eher bei größeren oder komplexen Projekten einen Mehrwert.



  • Ja, aber ich muss ja dann in den Kommentaren diese Tokens von Doxygen verwenden.

    Ich meinte: Ist es sinnvoll, seinen Quelltext SO (mit Doxygen-Tokens) zu kommentieren?



  • -Nachfrage- schrieb:

    Ok, meinst du, es ist sinnvoll, schon von anfang an so seinen Quelltext zu kommentieren, damit man später mit Doxygen eine Doku bauen kann?

    Das, was hier im Beispiel gezeigt wurde, ist vermutlich automatisch von irgendeiner IDE generiert worden. Ich halte es generell für eine gute Idee, seinen eigenen Quellcode vernünftig zu dokumentieren. ...und zwar relativ früh, weil man es später immer unwahrscheinlicher macht. Tags für Dokumentationswerkzeuge zu nutzen kann auch sehr sinnvoll sein, vor allem, wenn Du viele Klassen und so weiter hast und die Zusammenhänge irgendwann vielleicht nicht mehr kennst.

    Ich persönlich dokumentiere sehr unterschiedlich stark. Größtenteils mit Kommentaren im Rahmen von solcher Dokumentationstools, aber teilweise auch innerhalb der Methoden direkt im Quelltext. ...eine recht ausführlich dokumentierte Quellcode-Datei von mir wäre zum Beispiel folgende ( ⚠ schreckliches, schlechtes Englisch ⚠ ):

    /*
     * LineCaster.java
     *
     * Created on 8. März 2005, 01:25
     */
    
    package jaradap.model.algorithm;
    
    import jaradap.model.algorithm.multiPointProcessor.RaycastProcessor;
    import jaradap.model.data.BasicRaster;
    import jaradap.model.data.SingleChannelStandardRaster;
    import math.linearAlgebra.Vector;
    
    /**
     * This class represents Objects which can analyze lines in a given raster. The analysis
     * projects a line into a single value which is given by a RaycastProcessor, the raster and the line. 
     *
     * @author Gregor
     */
    public class LineCaster
    {
       private final RaycastProcessor pointProcessor;
       private final SingleChannelStandardRaster raster;
       private final int dimension;
    
       /** 
        * Creates a new LineCaster with the given parameters.
        *
        * @param pointProcessor This is the RaycastProcessor that will be used to analyze the lines 
        *                       in the method castLine.
        * @param raster This is the raster in that this LineCaster analyzes lines.
        */
       public LineCaster(final RaycastProcessor pointProcessor, final SingleChannelStandardRaster raster)
       {
          this.pointProcessor = pointProcessor;
          this.raster = raster;
          dimension = raster.getDimensions();
       }
    
       /**
        * This method analyzes the line specified by the parameters startPoint and endPoint. 
        * The pointProcessor of this LineCaster is used to compute the resulting value, while the 
        * raster of this LineCaster is the environment for the analysis.
        *
        * @param startPoint This is the start point of the line.
        * @param endPoint This is the end point of the line.
        * @return The value of the pointProcessor after processing all points of the line inside the raster
        *         will be returned. If the line has no points inside the raster, 0 will be returned.
        */
       public float castLine(final Vector startPoint, final Vector endPoint)
       {
          // Check parameters.
          if (startPoint.getDimension() != dimension)
             throw new IllegalArgumentException("startPoint has wrong dimension.");
          if (endPoint.getDimension() != dimension)
             throw new IllegalArgumentException("endPoint has wrong dimension.");
    
          // Clip line: 
          // Resulting line is given by rasterStartPoint and rasterEndPoint.
          final int[] rasterStartPoint = new int[dimension];
          final int[] rasterEndPoint = new int[dimension];
          if(!setFirstPointInRaster(rasterStartPoint,startPoint,endPoint)) return 0.0f;
          if(!setFirstPointInRaster(rasterEndPoint,endPoint,startPoint)) return 0.0f;
    
          // Init helper variables.
          int maxDiffIndex = 0;
          final int[] intDifferences = new int[dimension];
          final int[] relativePosition = new int[dimension];
          final int[] position = new int[dimension];
          final int[] increments = new int[dimension];
          for(int i = 0 ; i < dimension ; ++i)
          {
             intDifferences[i] = rasterEndPoint[i] - rasterStartPoint[i];
             increments[i] = (intDifferences[i] > 0) ? 1 : -1;
             intDifferences[i] = Math.abs(intDifferences[i]);
             if (intDifferences[i] > intDifferences[maxDiffIndex]) maxDiffIndex = i;
             relativePosition[i] = intDifferences[i] >> 1;
             position[i] = rasterStartPoint[i];
          }
          final int maxDifference = intDifferences[maxDiffIndex];
          final int maxIncrement = increments[maxDiffIndex];
    
          // Process line: 
          // 1. Reset pointProcessor.
          // 2. Process Bresenham-Line-Algorithm
          // 3. Return value of pointProcessor
          pointProcessor.reset();
          for(;position[maxDiffIndex] != rasterEndPoint[maxDiffIndex] ; position[maxDiffIndex] += maxIncrement)
          {
             if (pointProcessor.addPoint(raster,position)) return pointProcessor.getValue();
             for(int i = 0 ; i < dimension ; ++i)
             {
                if (i == maxDiffIndex) continue;
                relativePosition[i] += intDifferences[i];
                if (relativePosition[i] < maxDifference) continue;
                position[i] += increments[i];
                relativePosition[i] -= maxDifference;
             }
          }
          pointProcessor.addPoint(raster,position);
          return pointProcessor.getValue();
       }
    
       private final boolean setFirstPointInRaster(final int[] target, final Vector firstLinePoint,
                                                   final Vector lastLinePoint)
       {
          // Compute the distance of the line's start- and endpoint in each direction.
          final double[] distances = new double[dimension];
          double fraction = 0.0;
          for (int i = 0 ; i < dimension ; ++i)
          {
             distances[i] = (float)(lastLinePoint.getComponent(i) - firstLinePoint.getComponent(i));
          }
    
          // Compute the fraction that represents the point where the line enters the raster.
          for (int i = 0 ; i < dimension ; ++i)
          {
             double newFraction = 0.0;
             final double component = firstLinePoint.getComponent(i);
             final double difference = distances[i];
             final double maxValue = raster.getSize(i) - 1;
             if (component < 0.0)
             {
                if (difference <= 0.0) return false;
                newFraction = component / difference;
             }
             else if (component > maxValue)
             {
                if (difference >= 0.0) return false;
                newFraction = (component - maxValue) / difference;
             }
             if (newFraction < fraction) fraction = newFraction;
          }
    
          // Use the fraction to compute the first point of the line that lies within the raster
          // and check if the point really lies within the raster.
          // The point may not lie within the raster if there is no point of the line in the raster.
          for (int i = 0 ; i < dimension ; ++i)
          {
             target[i] = Math.round((float)(firstLinePoint.getComponent(i) - fraction * distances[i]));
             if (target[i] < 0) return false;
             if (target[i] > raster.getSize(i) - 1) return false;
          }
          return true;
       }
    }
    

    ...aber es kann auch vorkommen, dass ich Dinge gar nicht kommentiere, so wie das da zum Beispiel:

    /*
     * MedianFilter.java
     *
     * Created on 20. März 2005, 17:37
     */
    
    package jaradap.model.algorithm;
    
    import controller.*;
    import controller.descriptor.*;
    import jaradap.model.algorithm.edgeHandler.EdgeHandler;
    import jaradap.model.algorithm.edgeHandler.NearestElementEdgeHandler;
    import jaradap.model.algorithm.edgeHandler.RemapRaxelEdgeHandler;
    import jaradap.model.algorithm.hierarchical.LocalNeighborhoodTransformer;
    import jaradap.model.algorithm.multiPointProcessor.MedianPointProcessor;
    import jaradap.model.algorithm.neighborhood.*;
    import jaradap.model.data.SingleChannelStandardRaster;
    
    /**
     *
     * @author Gregor Michalicek
     */
    @MenuStructure({"Process","Median Filter..."})
    @Name("Median Filter")
    public class MedianFilter implements DataProcessor<SingleChannelStandardRaster,SingleChannelStandardRaster>
    {
       private final LocalNeighborhood neighborhood;
       private final EdgeHandler edgeHandler;
    
       /** Creates a new instance of MedianFilter */
       @Name("Default Construction")
       public MedianFilter
          (
             final @Name("Radius") @FloatBounds(defaultValue = 1.0f, max = 10.0f) float radius,
             final @Name("Distance Type") @DefaultClass(EuclideanDistance.class) Distance distance,
             final @Name("Edge Handler") @DefaultClass(NearestElementEdgeHandler.class) EdgeHandler edgeHandler
          )
       {
          if (radius < 0) throw new IllegalArgumentException("radius is negative.");
          if (distance == null) throw new NullPointerException("distance is null.");
          if (edgeHandler == null) throw new NullPointerException("edgeHandler is null.");
          neighborhood = new LocalNeighborhood(radius, distance);
          this.edgeHandler = edgeHandler;
       }
    
       public SingleChannelStandardRaster processData(final SingleChannelStandardRaster inData)
       {
          if (inData == null) throw new NullPointerException("inData is null.");
          final SingleChannelStandardRaster outRaster = ControllerMethods.createCopy(inData);
          final LocalNeighborhoodTransformer neighborhoodTransformer = 
             new LocalNeighborhoodTransformer(neighborhood,new MedianPointProcessor(),outRaster,edgeHandler);
          neighborhoodTransformer.processRaster(inData);
          return outRaster;
       }
    
    }
    


  • Zeus schrieb:

    Yup, und wie Gregor schon verlinkt hat:

    Hmm, und wenn man jetzt zwischen dem Öffnen der verschiedenen Dateien etwas lesen will, wie sieht das dann aus?



  • Also ich dokumentiere zu wenig. Aber wenn ich dokumentiere, dann dokumentiere ich das, was mir am wenigsten nachvollziehbar erscheint. Eine Klasse sollte immer eine Erklärung erhalten, Parameter erhalten bei mir aber in aller Regel wenig Erklärung, denn die sollten bei dem Methodennamen (evtl. plus Erklärung dazu) in Zusammenhang mit der Klasse selbsterklärend sein - außer man hat optionale Parameter oder so ungenauen Müll (habe ich leider noch viel zu oft), dann braucht man leider Kommentare.

    Was ich aber nie habe ist so was wie

    @param startPoint This is the start point of the line.

    , weil das einfach Platz kostet und nichts hilft.

    Aber gut, wenn nachher eine HTML-Dokumentation rauskommen soll, geht es natürlich gar nicht wenn ein selbsterklärender Parameter nicht erklärt ist, gehört einfach zu einem harmonischen Gesamtbild. (die Aussage soll schon die Ironie fangen, dass selbsterklärende Parameter nicht erklärt werden müssen, gleichzeitig aber auch eingestehen, dass eine Doku mit Lücken scheiße wirkt, insgesamt also ein Zugeständnis an den Stil, wenngleich man den Code verschändelt, damit nachher eine HTML-Dokumentation schön aussieht - aber gut, das ist halt wirtschaftlich und somit trotzdem okay)



  • Javadoc ist ein riesen Vorteil finde ich.
    Es baut dir nicht nur die html Seiten, der gesamte Java Quelltext ist so kommentiert und das Javadoc kann auch direkt in deine IDE z.b. Eclipse integriert werden, dass es direkt angezeigt wird.

    die @ Dinger nennt man Annotations. Es gibt Kommentar Annotations und Code Annotations, die funktionieren so ähnlich wie Interfaces, oder können zur Laufzeit was zuweisen. In kommentaren kann man damit z.B. auf andere Kassen und Methoden verweisen, z.B. @see{Integer#toString} würde in dem Kommentar auf die toString Methode von Integer verweisen...

    Generell ist es bei Java Entwickler üblich den Code gut zu kommentieren, zumindest den Header einer Methode (jaja, ich weiß guter C Code ist selbsterklärend und benötigt keine Kommentare 😉 so sagen es zumindest immer unsere C Entwickler)


Anmelden zum Antworten