Java EXE

0

Witam

Mam dwa pytanka. Na pierwsze mam dość mętne odpowiedzi z google, więc sprecyzuję pytanie pod swoje potrzeby.

  1. Czy Java na Windows może wygenerować EXE działający pod ten system ? Chodzi o to bym dał komuś program w Java (sam exe) i ta osoba żeby nie musiała ustawiać żadnych CLASSPATH itp tylko dostała samodzielny plik wykonywalny działający pod każdym OS tak jak to robi np: Delphi.

  2. Czy do Java można wstawić kod z innego pliku jak w C++ za pomocą #include<nazwa.pliku> ?
    Chciałbym np: mieć samo ciało klasy tak by nie było już w nim nawiasów { } itp albo samo ciało metody.

przykładowo:

class Klasa {
{
void metoda (){
#include<cialo.metody> ?
}
}

z góry dziękuję za odpowiedzi.

0
  1. Tak np. http://www.jar2exe.com/ musisz najpierw wygenerować .jar. Pamiętaj że i tak użytkownik musi mieć maszyne Javy na komputerze.
  2. Tak, tutaj przykład : http://piotr-mitka.blogspot.com/2009/11/test.html.
0

dzięki za wyczerpującą odpowiedź.

Czyli C++ rządzi - z javą jest za dużo pieprzenia - nie dam laikowi programu w java bo sobie nie poradzi. Weź pod uwagę, że są ludzie co nie potrafią nic instalować ale za to potrafią odpalić exe xD

Java jest trochę bardziej automatyczna niż C++, ale ten z kolei generuje normalne EXE i jest dużo szybszy.

PS: która to komenda wstawia kod z pliku - System.loadLibrary("HelloWorld") ??

0
  1. Czy Java na Windows może wygenerować EXE działający pod ten system ? Chodzi o to bym dał komuś program w Java (sam exe) i ta osoba żeby nie musiała ustawiać żadnych CLASSPATH itp tylko dostała samodzielny plik wykonywalny działający pod każdym OS tak jak to robi np: Delphi.

Jeśli chodzi o samo odpalanie programów w Javie to nie trzeba od dawna żadnych CLASSPATH ustawiać. Tworzysz JARa z manifestem, a użytkownik po prostu dwukrotnie klika na niego. Sama instalacja Javy jest prosta jak budowa cepa - wystarczy ściągnąć instalator i klikać Dalej.

  1. Czy do Java można wstawić kod z innego pliku jak w C++ za pomocą #include<nazwa.pliku> ?
    Chciałbym np: mieć samo ciało klasy tak by nie było już w nim nawiasów { } itp albo samo ciało metody.

Kod Javy oczywiście daje się dzielić na metody, klasy, pliki i JARy.

Poza tym: chcesz ładować moduły natywne w Javie czy po prostu podzielić kod Java na wiele plików? Łączenie C++ z Javą bez wyraźnej potrzeby jest bez sensu i przypomina walenie głową w ścianę dla relaksu.

0

Nie chcę robić metod natywnych - chcę zdefiniować klasę i metody a ciała metod chcę mieć w osobnych plikach.

Np:

plik1:

class Klasa {
void metoda(){
#include plik2
}
}


plik2:

System.out.print("text");

Jeśli mam 2 takie pliki to poprawianie błędów jest bardziej przejrzyste.

0
  1. W Javie nie musisz robić plików nagłówkowych, tych z końcówką .h. Zamiast tego robisz po prostu import klasy, której chcesz użyć. Np masz klasę z jakimiś tam metodami:
package paczka1;

class Klaska {
    static public void róbCoś() {
    // nieważne
    }
}

I teraz możesz użyć jej w innej klasie:

package paczka2;

import paczka1.Klaska;

class InnaKlaska {
  void treleMorele() {
    Klaska.róbCoś();
  }
}

Package w Javie to mniej więcej jak namespace w C++ tyle, że łatwo się je zagnieżdża, czyli za pomocą kropek, a nie zagnieżdżeń.

  1. Jeżeli tworzysz bibliotekę lub z innego powodu chcesz mieć odchudzony interfejs dla swojej klaski to tworzysz właśnie interfejs, czyli klasę w pełni abstrakcyjną i bez pól. Tworzysz ją za pomocą słówka kluczowego interface (w przeciwieństwie do słówka kluczowego class w przypadku klas).

Te rzeczy są zwykle w początkowych wersjach kursów Javy. Wystarczy wziąć cokolwiek trzymającego poziom do ręki i od razu zobaczysz co i jak w Javie.

0

Wibowit ja to wiem, ale nie o to się pytałem. Szukam kogoś kto zna C++ na tyle, że wie iż instrukcja #include<> oprócz implementowania biblioteki ma również funkcję wstawiania treści pliku między linijki kodu co przekłada się na większą czytelność.

0

Nie ma takiej możliwości. W Javie nie ma #include ani odpowiednika, bo to jest po prostu zbędne. Klasa i tak powinna nie być zbyt długa, a jeżeli jest, to należy ją podzielić na mniejsze, a nie wydzielać części ciał metod do osobnych plików. W C++ podejrzewam że też tak się nie robi, mimo że można.

0

Szkoda. To, że czegoś się nie robi do mnie nie przemawia. Ja robię: ) Używam też instrukcji goto w Delphi mimo, że tak też się nie robi a C++ z include jest dla mnie językiem mega przejrzystym i podejrzewam, że długo jeszcze będzie królem xD

0

Nie programujesz zawodowo, co? :)

0
krzysiek050 napisał(a):

Nie programujesz zawodowo, co? :)

Koledzy by go zjedli :P

Wibowit ja to wiem, ale nie o to się pytałem. Szukam kogoś kto zna C++ na tyle, że wie iż instrukcja #include< oprócz implementowania biblioteki ma również funkcję wstawiania treści pliku między linijki kodu co przekłada się na większą czytelność.

Wiem jak działa #include w C/ C++. Jest to zwykłe wklejenie zawartości pliku. Wątpię, by ktokolwiek poważny robił to co ty, bo takie cięcie funkcji na pliki rozwala wsparcie od IDE, a duże funkcje ciężko się testuje. Nie widzę też w jaki sposób miałoby to być lepsze od zwykłego podziału dużej funkcji na mniejsze.

Z ciekawości spytam: jakie jest u ciebie pokrycie kodu automatycznymi testami?

0

Jest takie powiedzonko: You can write Fortran in any language.
To chyba właśnie jego wyznawca, ale są trudności z tym "any" w przypadku Javy. ;P

0

Krzysiek050
Nie programujesz zawodowo, co?

Wiesz...nie pracuję jako programista, ale piszę czasem programy na zamówienie.

Wibowit
Wątpię, by ktokolwiek poważny robił to co ty, bo takie cięcie funkcji na pliki rozwala wsparcie od IDE, a duże funkcje ciężko się testuje.

Gdyby takie coś było niepoważne i rozwalało wsparcie "od IDE" to myślę, że projektant/ci C++ po prostu by takiej funkcji nie zaimplementowali. Skoro dali możliwość takiej składni dla programistów myślę, że ma to swój sens i tylko twój wybór zależy od tego czy chcesz z tego korzystać czy nie. Ja osobiście widzę w tej funkcji niesamowicie dużą wygodę i ją stosuję. Dzięki temu mam mniejszy kod do jednorazowej analizy i jest mi po prostu łatwiej. Jak uważasz, że tobie to utrudnia pracę to stosuj sobie styl jaki uważasz za stosowny.

Co innego jest z instrukcją goto - również zawsze mnie śmieszyło uważanie tego za "zły" styl. Styl to styl - ja stosuję to bardzo rzadko ale bywają sytuację, że mi po prostu ułatwia to pracę. Moje projekty sięgają czasem tysięcy linijek kodu i np: poprawienie jakiegoś błędu ułatwia mi wdrożenie goto niż rekonstrukcja całej procedury gdzie znowu musiałbym uwzględnić kilka warunków. Skoro projektanci dają mi takie rozwiązania to je stosuję wedle swoich potrzeb. Programowałem kiedyś w asemblerze i dla mnie osobiście goto jest wygodne - co innego jak ktoś używałby tego non-top - wtedy faktycznie scrollowanie co chwila strony do odpowiedniego kodu może być upierdliwe - dlatego mówię - wszystko można użyć o ile robi się to w granicach rozsądku. U mnie szczerze mówiąc goto zawsze idzie na "end" procedury (jeśli już muszę tego użyć)

Z ciekawości spytam: jakie jest u ciebie pokrycie kodu automatycznymi testami?

Nie jestem zawodowym programistą i nie robię autotestów - jak napiszę program sam go testuję i poprawiam na bieżąco.

2

Gdyby takie coś było niepoważne i rozwalało wsparcie "od IDE" to myślę, że projektant/ci C++ po prostu by takiej funkcji nie zaimplementowali.

Wątpię, by projektanci C jakoś mocno przejmowali się wsparciem dla IDE, bo #include jest konstrukcją starszą niż jakiekolwiek IDE.

Też robię projekty na tysiące linijek i też programowałem w asemblerze (asembler.republika.pl). Nie musisz się tak prężyć.

Brak testów automatycznych, wielkie funkcje i używanie goto sugeruje, że bardzo boisz się przebudowywać swój kod, bo musiałbyś go dogłębnie testować ręcznie od nowa. Zamiast zmieniać kod tak by był bardziej elastyczny, unikasz szerokich zmian gmatwając kod.

Podaj przykład w którym twoje dziwaczne użycie #include poprawia twoim zdaniem sytuację.

1

Gwoli ścisłości, proszę nie obwiniać projektantów C++ za #include. C++ odziedziczyło go po C dla kompatybilności wstecznej. Jest to mechanizm z lat chyba jeszcze 70-tych, na tyle archaiczny, że żaden nowoczesny język programowania nie realizuje modułów w ten sposób (może poza PHP :D). W czasach, koedy powstawał, nikomu się nie śniło o C++. W C++ użycie makr preprocesora C nie jest zalecane i jedyna potrzeba jego użycia to właśnie #include do relalizacji modułów, wynikające z ułomności C++ względem innych języków. Słyszałem, że niedługo C++ też ma doczekać się modułów z prawdziwego zdarzenia i ostatni bastion preprocesora C upadnie. Java, Delphi, C#, Python, Ruby, Haskell, Rust, D wszsystkie mają wbudowany znacznie lepszy mechanizm do podziału kodu na mniejsze części, więc nie potrzebują do szczęścia archaicznego preprocesora C.

Jak chcesz dzielić kod Javy na mniejsze części, to rób o profesjonalnie, korzystając z klas i pakietów. Jest to mechanizm lepszy pod chyba każdym względem niż #include.

Oczywiście, jeśli ktoś się uprze, to nic nie stoi na przeszkodzie używać preprocesora C do Javy, tak jak się używa do C++. Przepuść kod Javy przez gcc -E i zrobione. Tylko serio, nie wiem, po co. Nic nie zyskujesz a rozwalasz sobie choćby wsparcie IDE.

0

Jeśli budujecie klasę, która ma powiedzmy 15 metod albo 25 - to dla mnie bardzo wygodnie jest mieć ciało każdej metody w osobnym pliku i nie widzę tu żadnego archaizmu. Jak ktoś lubi przeglądać klasę, która ma 450 linijek kodu to jego sprawa. Ja lubię mieć 25 plików nazwanych jak metoda i mam do tego szybszy dostęp - z tym nie ma co dyskutować czy jest to dobre czy złe bo to w ogóle nie wpływa na wydajność - ot po prostu - albo programista lubi w ten sposób pisać kod albo nie - C/C++ daje taką elastyczność - Java nie.

Ja szczerze mówiąc nie bardzo rozumiem co ma tu IDE do include. Można powiedzieć, że taką namiastkę dają klasy w osobnych plikach a include jeszcze bardziej daje możliwość podziału kodu jeśli jest on faktycznie przydługi.

0

A jak masz przeładowane funkcje w klasie, to masz pliki o takich samych nazwach? Iterujesz je? A jak potem podczas refactoringu pasuje wywalić jakaś ze środka to przesuwasz indexy i zmieniasz includy, czy masz dziure w numeracji?

Takie pytanie: Jak duze są projekty, które piszesz? Tak mniej więcej - ile mają linii kodu?

0

Jeśli typowa klasa ma u ciebie 450 linijek to prawdopodobnie robisz coś źle, tzn twoja klasa robi zbyt dużo rzeczy naraz.

Przechodząc do twojego problemu (zakładając, że dalej chcesz pisać wielkie klasy).

Ja szczerze mówiąc nie bardzo rozumiem co ma tu IDE do include.

Załóżmy, że mamy taki kod (treść nieważna):

/**
 * Copyright (C) 2015 Piotr Tarsa ( http://github.com/tarsa )
 *
 * This software is provided 'as-is', without any express or implied
 * warranty.  In no event will the author be held liable for any damages
 * arising from the use of this software.
 *
 * Permission is granted to anyone to use this software for any purpose,
 * including commercial applications, and to alter it and redistribute it
 * freely, subject to the following restrictions:
 *
 * 1. The origin of this software must not be misrepresented; you must not
 * claim that you wrote the original software. If you use this software
 * in a product, an acknowledgment in the product documentation would be
 * appreciated but is not required.
 * 2. Altered source versions must be plainly marked as such, and must not be
 * misrepresented as being the original software.
 * 3. This notice may not be removed or altered from any source distribution.
 *
 */
#ifndef NUMBERCODEC_HPP
#define	NUMBERCODEC_HPP

#include <cstdint>

namespace tarsa {

    class NumberCodec {
    public:

        enum error_t {
            OK, NegativeBufferSize, NegativeValue, ValueOverflow,
            BufferOverflow, BufferUnderflow
        };

    protected:
        ssize_t bufferPosition;
        ssize_t const bufferSize;
        error_t error;

    public:

        NumberCodec(ssize_t const bufferSize) : bufferPosition(0),
        bufferSize(bufferSize) {
            error = bufferSize < 0 ? NegativeBufferSize : OK;
        }

        ssize_t getBufferPosition() {
            return bufferPosition;
        }

        error_t getError() {
            return error;
        }

        char const * showError() {
            switch (error) {
                case OK: return "OK";
                case NegativeBufferSize: return "NegativeBufferSize";
                case NegativeValue: return "NegativeValue";
                case ValueOverflow: return "ValueOverflow";
                case BufferOverflow: return "BufferOverflow";
                case BufferUnderflow: return "BufferUnderflow";
                default: return nullptr;
            }
        }

    };

    class NumberEncoder : public NumberCodec {
        int8_t * const buffer;
    public:

        NumberEncoder(int8_t * const buffer, ssize_t const bufferSize) :
        buffer(buffer), NumberCodec(bufferSize) {
        }

        void serializeInt(int32_t const value) {
            if (error == OK) {
                if (value < 0) {
                    error = NegativeValue;
                } else if (bufferPosition == bufferSize) {
                    error = BufferOverflow;
                } else if (value <= INT8_MAX) {
                    buffer[bufferPosition++] = value;
                } else {
                    buffer[bufferPosition++] = (value & 127) - 128;
                    serializeInt(value >> 7);
                }
            }
        }

        void serializeLong(int64_t const value) {
            if (error == OK) {
                if (value < 0) {
                    error = NegativeValue;
                } else if (bufferPosition == bufferSize) {
                    error = BufferOverflow;
                } else if (value <= INT8_MAX) {
                    buffer[bufferPosition++] = value;
                } else {
                    buffer[bufferPosition++] = (value & 127) - 128;
                    serializeLong(value >> 7);
                }
            }
        }
    };

    class NumberDecoder : public NumberCodec {
        int8_t const * const buffer;

    public:

        NumberDecoder(int8_t const * const buffer, ssize_t const bufferSize) :
        buffer(buffer), NumberCodec(bufferSize) {
        }

    private:

        int32_t deserializeInt0(int32_t const current, int32_t const shift) {
            if (error == OK) {
                if (bufferPosition == bufferSize) {
                    error = BufferUnderflow;
                    return -1;
                } else {
                    int8_t const input = buffer[bufferPosition++];
                    if (input == 0) {
                        return current;
                    } else {
                        int32_t const chunk = input & 127;
                        if ((chunk != 0) && ((shift > 31)
                                || (chunk > (INT32_MAX >> shift)))) {
                            error = ValueOverflow;
                            return -1;
                        } else {
                            int32_t const next = (chunk << shift) + current;
                            if (input > 0) {
                                return next;
                            } else {
                                return deserializeInt0(next, shift + 7);
                            }
                        }
                    }
                }
            }
        }

        int64_t deserializeLong0(int64_t const current, int32_t const shift) {
            if (error == OK) {
                if (bufferPosition == bufferSize) {
                    error = BufferUnderflow;
                    return -1;
                } else {
                    int8_t const input = buffer[bufferPosition++];
                    if (input == 0) {
                        return current;
                    } else {
                        int64_t const chunk = input & 127;
                        if ((chunk != 0) && ((shift > 63)
                                || (chunk > (INT64_MAX >> shift)))) {
                            error = ValueOverflow;
                            return -1;
                        } else {
                            int64_t const next = (chunk << shift) + current;
                            if (input > 0) {
                                return next;
                            } else {
                                return deserializeInt0(next, shift + 7);
                            }
                        }
                    }
                }
            }
        }

    public:

        int32_t deserializeInt() {
            return deserializeInt0(0, 0);
        }

        int64_t deserializeLong() {
            return deserializeLong0(0L, 0);
        }


    };
}

#endif	/* NUMBERCODEC_HPP */

NetBeans bardzo ładnie mi go koloruje:
b91706c414.png
Jeśli z jakiegoś powodu wytnę sobie ciało funkcji i przeniosę do innego pliku to tracę całe wsparcie od IDE:
a36556565b.png
Oprócz kolorowania tracę chociażby podpowiadanie, nawigację i sprawdzanie błędów składniowych w trakcie pisania.

Teraz może pokażę jak się pracuje w świecie Javowym na przykładzie IntelliJ IDEA.

Po pierwsze, jeśli lubimy bardzo widzieć listę metod to jest opcja "Show Members" i prezentuje się to tak:
b056b01995.png
Jak widać, jest lista wszystkich metod i pól z klasy (tutaj pól nie ma, ale jak dołożę to się pojawią w drzewku z lewej). Po dwukliku przechodzimy do metody.
Z czegoś takiego zwykle się jednak nie korzysta i ta opcja jest domyślnie wyłączona (nie powinno być problemu z jej włączeniem, to dosłownie dwa kliknięcia).

Normalni Javowcy korzystają z nawigacji będącej dzisiaj podstawą IDE. Zamiast samemu się produkować odsyłam do gotowej próbki możliwości: https://medium.com/@andrey_cheptsov/top-20-navigation-features-in-intellij-idea-ed8c17075880
Jako wieloletni użytkownik IntelliJ zapewniam, że nawigacja w nim jest superszybka.

0

misiakufal
Takie pytanie: Jak duze są projekty, które piszesz? Tak mniej więcej - ile mają linii kodu?

od 1k do 5k linijek.

Co do odpowiedzi Wibowita to racja, nowoczesne kompilatory radzą sobie jakoś z estetyką i czytelnością - aczkolwiek C++ nadal daje taką możliwość i ja bym z niej korzystał - ale wcale nie jest powiedziane, że nie można mieć czytelnego kodu bez #include. To jedynie wybór. Ja osobiście lubię mieć taką możliwość gdyż przyzwyczaiłem się do tego z C - najwidoczniej pora zmienić przyzwyczajenia: )

0

Kurde czemu jakiś leming może mi pisać w stopce (wizzie) ? : (

0

Do autora wątku pkt. 2:

  • to jak używasz #include można określić jako (cytuję z głowy) "to jest takie moje specjalne programowanie"

Jeśli chcesz programować tak jak Ci wygodnie, ponieważ nikt nie czyta Twojego kodu - to rób to i nie zawracaj głowy innym.
Ściągnij sobie: https://sourceforge.net/projects/hashinclude/
i życzę udanej zabawy.
BTW, to co zaprezentowałeś nie jest stosowane nawet w C/C++.

Jeśli chcesz pisać jak reszta świata (bo np. znudzi Ci się freelancerka albo chciałbyś być częścią większego projektu) to weź sobie do serca uwagi od @Wibowit.

0

Mnie nigdy nie obchodziła reszta świata - czyli jak robią i co robią inni. Zapytałem się was czy jest odpowiednik #include w Java bo nie mogłem tego szybko znaleźć w google a wprawny programista Java odpowie mi wystarczająco jasno, za co dziękuję.

Poza tym zabawne są komentarze Wizzie odnośnie kompilatora i IDE gdyż w języku potocznym na IDE mówi się kompilator mimo, że sam kompilator to jedynie składowa IDE.

Zgadzam się z Wibowitem i przyznaję rację, że można trzymać wysoki poziom czytelności kodu bez #include lecz trzeba też pamiętać, że nie na każdym komputerze NetBeans chodzi satysfakcjonująco i zdarzają się maszyny (przynajmniej u mnie) gdzie odpowiednik #include zwiększyłby elastyczność projektu.

Temat uważam za wyczerpany i dziękuję wszystkim, którzy treściwie odpowiedzieli na moje pytanie.

1 użytkowników online, w tym zalogowanych: 0, gości: 1