Zielony Smok - logo witryny

Launch Single-File Source-Code Programs – dosł. Uruchamianie jednoplikowych programów z kodu źródłowego.

Źródło: https://openjdk.java.net/jeps/330

Ideą jest uruchamianie plików z rozszerzeniem .java bezpośrednio z narzędzia
java bez użycia narzędzia javac.

Przykłady

  • Klasa Now – prosta klasa
  • Klasa Primes – klasa wymagająca podania argumentów
  • Klasa Primes2 – użycie opcji --source (wskazanie wersji Java)
  • Klasa Curve05 – więcej niż jedna klasa w pliku źródłowym
  • Klasa TestJaver – klasa wymagająca modułu
Klasa Now
package launchsinglefile;
import java.time.*;
public class Now {
    public static void main(String[] args) {
        Instant now = Instant.now();
        System.out.println("Chwila teraźniejsza: " + now);
    }
}
Klasa Primes
package launchsinglefile;
import java.util.*;
public class Primes {
    public static void main(String[] args) {
        print(getPrimes(Long.parseLong(args[0]), Long.parseLong(args[1])));
    }
    /**
     * oblicza liczby pierwsze w podanym zakresie
     *
     * @param min long - pierwsza liczba
     * @param max long - większa liczba
     * @return ArrayList<Integer> - arraylista liczb pierwszych
     * leżących między min, a max
     */
    public static ArrayList<Long> getPrimes(long min, long max) {
        ArrayList<Long> list = new ArrayList<>();
        for (long j = min + 1; j < max; j++) {
            if (isPrime(j)) {
                list.add(j);
            }
        }
        return list;
    }
    public static boolean isPrime(long n) {
        for (long j = 2; Math.pow(j, 2) <= n; j++) {
            if (n % j == 0) {
                return false;
            }
        }
        return true;
    }
    // drukuje arrayliste z danymi dowolnego typu
    // w przypadku typow numerycznych uzywac typow otoczkowych
    // a nie prostych czyli Double a nie double;
    public static <T> void print(ArrayList<T> array) {
        for (int i = 0; i < array.size(); i++) {
            if (i < array.size() - 1) {
                System.out.print(array.get(i) + ", ");
            } else {
                System.out.print(array.get(i));
            }
        }
    }
}
Klasa Primes2
package launchsinglefile;
import java.util.*;
public class Primes2 {
    public static void main(String[] args) {
        var array = getPrimes(Long.parseLong(args[0]), Long.parseLong(args[1]));
        print(array);
    }
    /**
     * oblicza liczby pierwsze w podanym zakresie
     *
     * @param min long - pierwsza liczba
     * @param max long - większa liczba
     * @return ArrayList<Integer> - arraylista liczb pierwszych
     * leżących między min, a max
     */
    public static ArrayList<Long> getPrimes(long min, long max) {
        ArrayList<Long> list = new ArrayList<>();
        for (long j = min + 1; j < max; j++) {
            if (isPrime(j)) {
                list.add(j);
            }
        }
        return list;
    }
    public static boolean isPrime(long n) {
        for (long j = 2; Math.pow(j, 2) <= n; j++) {
            if (n % j == 0) {
                return false;
            }
        }
        return true;
    }
    // drukuje arrayliste z danymi dowolnego typu
    // w przypadku typow numerycznych uzywac typow otoczkowych
    // a nie prostych czyli Double a nie double;
    public static <T> void print(ArrayList<T> array) {
        for (int i = 0; i < array.size(); i++) {
            if (i < array.size() - 1) {
                System.out.print(array.get(i) + ", ");
            } else {
                System.out.print(array.get(i));
            }
        }
    }
}
Klasa Curve05
package launchsinglefile;
import java.awt.*;
import javax.swing.*;
public class Curve05 extends JFrame {
    /**
     *
     */
    private static final long serialVersionUID = 5533707010593453907L;
    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> new Curve05(new Lissajous()));
    }
    public Curve05(JComponent comp) {
        setLayout(null);
        int fw = 1000;
        int fh = 1000;
        setPreferredSize(new Dimension(fw, fh));
        setBounds((Toolkit.getDefaultToolkit().getScreenSize().width / 2)
                        - (fw / 2),
                (Toolkit.getDefaultToolkit().getScreenSize().height / 2)
                        - (fw / 2), fw, fh);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setTitle("Ramka Graficzna");
        //  setResizable(false);
        JPanel panel = (JPanel) comp;
        panel.setLocation((fw - panel.getWidth()) / 2,
                (fh - panel.getHeight()) / 2);
        add(panel);
        setVisible(true);
    }
}
class Lissajous extends JPanel {
    private static final long serialVersionUID = -7271420472998056247L;
    private static final int w = 800;
    private static final int h = 800;
    public Lissajous() {
        setPreferredSize(new Dimension(w, h));
        setSize(w, h);
        setBackground(Color.WHITE);
    }
    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g;
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_ON);
        lissajous(g2, Color.MAGENTA, 150, 70, 3, 4, Math.PI / 4.0,
                Math.PI / 2.0, 1000);
    }
    public static void lissajous(Graphics2D g2, Color kolor, int A1, int A2,
                                 int w1, int w2, double fi1, double fi2, int liczbaPunktow) {
        g2.setColor(kolor);
        g2.translate(400, 400);
        int x1 = (int) (A1 * Math.cos(fi1));
        int y1 = (int) (A2 * Math.cos(fi2));
        int x2;
        int y2;
        for (int i = 0; i < liczbaPunktow; i++) {
            double t = i * Math.PI / 360;
            x2 = (int) (A1 * Math.cos(w1 * t + fi1));
            y2 = (int) (A2 * Math.cos(w2 * t + fi2));
            g2.drawLine(x1, y1, x2, y2);
            x1 = x2;
            y1 = y2;
        }
    }
}
Klasa TestJaver
package launchsinglefile;
import java.io.*;
import java.net.*;
import java.net.http.*;
class TestJaver {
    public static void main(String[] args) {
        HttpClient client = HttpClient.newHttpClient();
        try {
            HttpRequest req = HttpRequest.newBuilder().uri(new URI("https://bajki.blog")).GET().build();
            HttpResponse<String> res = client.send(req, HttpResponse.BodyHandlers.ofString());
            int statusCode = res.statusCode();
            String body = res.body();
            System.out.println("Kod statusu 1: " + statusCode);
            //System.out.println("Ciało odpowiedzi 1: " + body);
            res = client.send(req, HttpResponse.BodyHandlers.ofString());
            statusCode = res.statusCode();
            //body = res.body();
            System.out.println("Cialo odpowiedzi 2: " + statusCode);
            //System.out.println("body 2: " + body);
        } catch (URISyntaxException | IOException | InterruptedException e) {
            e.printStackTrace();
        }
    }
}

Praca z linią poleceń

Przyjęłam, że pliki klas *.java są umieszczone – podobnie jak u mnie – folderze c:/java. Na komputerze zmienna JAVA_HOME wskazuje na OpenJDK-11.0.1.

Klasa Now

Jest to prosta klasa pokazująca aktualny czas.

Uruchamiamy linię poleceń i wpisujemy jak na obrazku (Rys. 152). Wynik pojawia się po chwili.

Launch Single-File Source-Code Programs
Rys. 152. Uruchomienie prostej klasy
Klasa Primes

Klasa oblicza liczby pierwsze w zakresie od args[0] do args[1], a zatem wymaga podania argumentów.

Uruchamiamy linię poleceń i wpisujemy jak na obrazku (Rys. 153).

Launch Single-File Source-Code Programs
Rys. 153. Uruchomienie klasy wymagającej podania argumentów
Klasa Primes2

Klasa tylko tym rożni się od klasy Primes, że używa słowa var, które weszło dopiero w
Java 10.

Konieczne jest użycie opcji --source (wskazanie wersji Java).

Launch Single-File Source-Code Programs
Rys. 154. Użycie niepoprawnej opcji –source

Wskazaliśmy zbyt wczesną wersję Java.

Launch Single-File Source-Code Programs
Rys. 155. Użycie poprawnej opcji –source

Tutaj wstawiliśmy poprawną wersję Java.

Klasa Curve05

W pliku Curve05.java mamy dwie klasy, z których jedna jest publiczna. Nie ma problemów z uruchomieniem (Rys. 156). W oknie pojawia się obraz krzywej.

Launch Single-File Source-Code Programs
Rys. 156. Wynik uruchomienia pliku zawierającego dwie klasy

Po zamknięciu okna sterowanie wraca do inii poleceń (Rys. 157).

Launch Single-File Source-Code Programs
Rys. 157. Uruchomienie pliku zawierającego dwie klasy
Klasa TestJaver

Klasa wymagająca modułu java.net.http. Klasa Curve05 też wymagała modułu java.desktop.

Jak widzimy klasa uruchamia się bez problemu mimo braku pliku module-info.java (Rys. 158)
wskazującego wymagane moduły. Dlaczego?

Launch Single-File Source-Code Programs
Rys. 158. Uruchomienie pliku klasy wymagającej modułu Java

Kod jest kompilowany i uruchamiany jako część modułu nie nazwanego z użyciem opcji
--add-modules=ALL-DEFAULT co pozwala na kompilację i wykonanie kodu.