Autor Wątek: Java kilka podstawowych pytań  (Przeczytany 2781 razy)

Offline LizarD

  • Użytkownik

# Sierpień 03, 2014, 15:57:36
Witam!

Mam parę pytań odnośnie Javy, nie rozumiem kilku rzeczy:

1. Interfejs a klasa abstrakcyjna, czym to się różni ?
Wiem że w interfejsie deklaruje się tylko metody bez ciał funkcji,
ale czy w interfejsie mogą być zmienne ? W klasie abstrakcyjnej
mogą być funkcje abstrakcyjne bez ciał mogą być zmienne i mogą być
funkcje nie abstrakcyjne, ale czy chodzi o coś jeszcze ?

2. Statyczne i niestatyczne klasy składowe, czyli:
public class Klasa {

public static class KlasaSkładowa {

}
}

Po co się robi coś takiego ?

3. Klasa anonimowa, Klasa lokalna, po co to się robi ?
4. Deklaruje swoją klasę:
pubic class Klasa {
int zmienna;
}
I rozumiem że jeżeli klasa jest typu public, a zmienna "zmienna" nie została określona czy jest typu public, private to jest typu public bo klasa jest typu public ?

Offline Mr. Spam

  • Miłośnik przetworów mięsnych

Offline magik6000

  • Użytkownik

# Sierpień 03, 2014, 16:34:10
1. W interfejsie możesz deklarować tylko(od javy 8 chyba) statyczne funkcje[i chyba zmienne - do sprawdzenia], tymczasem w klasach abstakcyjnych możesz pisać ciała zwykłych funkcji.

2. Statyczne klasy składowe mają dostęp tylko do pól statycznych 'kalsy-matki', tymczasem niestatyczne klasy mają dostęp do zwykłych pól i muszą zostać stworzone poprzez instancje klasy matki. Dobrze opisuje to ten kod:
/* Java program to demonstrate how to implement static and non-static
   classes in a java program. */
class OuterClass{
   private static String msg = "GeeksForGeeks";

   // Static nested class
   public static class NestedStaticClass{

       // Only static members of Outer class is directly accessible in nested
       // static class
       public void printMessage() {

         // Try making 'message' a non-static variable, there will be
         // compiler error 
         System.out.println("Message from nested static class: " + msg);
       }
    }

    // non-static nested class - also called Inner class
    public class InnerClass{

       // Both static and non-static members of Outer class are accessible in
       // this Inner class
       public void display(){
          System.out.println("Message from non-static nested class: "+ msg);
       }
    }
}

class Main
{
    // How to create instance of static and non static nested class?
    public static void main(String args[]){

       // create instance of nested Static class
       OuterClass.NestedStaticClass printer = new OuterClass.NestedStaticClass();

       // call non static method of nested static class
       printer.printMessage();   

       // In order to create instance of Inner class we need an Outer class
       // instance. Let us create Outer class instance for creating
       // non-static nested class
       OuterClass outer = new OuterClass();       
       OuterClass.InnerClass inner  = outer.new InnerClass();

       // calling non-static method of Inner class
       inner.display();

       // we can also combine above steps in one step to create instance of
       // Inner class
       OuterClass.InnerClass innerObject = new OuterClass().new InnerClass();

       // similarly we can now call Inner class method
       innerObject.display();
    }
}

3. Generalnie po to, żeby nie mieć syfu składającego się z miliona zmiennych

4. Modyfikator widoczności kalsy określa widoczność tej klasy. public - można używać wszędzie, protected - tylko w obrębie paczki, private - teoretycznie klasa mogła by używać tylko samą siebie, ale z tego co wiem nie da się tak zrobić. Pola klas nie zmieniają swojej widoczności, a domyślny jest zawsze public

Offline dynax

  • Użytkownik

# Sierpień 03, 2014, 17:06:42
1. W interfejsie możesz deklarować tylko(od javy 8 chyba) statyczne funkcje[i chyba zmienne - do sprawdzenia], tymczasem w klasach abstakcyjnych możesz pisać ciała zwykłych funkcji.

W klasie abstrakcyjnej możesz mieć już zdefiniowaną część funkcji a interfejs takich definicji zawierać nie może (co się co prawda trochę zmienia w javie 8). Poza tym klasa może w javie dziedziczyć tylko z jednej klasy nadrzędnej ale może implementować wiele interfejsów.

3. Generalnie po to, żeby nie mieć syfu składającego się z miliona zmiennych

No i dla tego że java jest w porównaniu do takiego c# ubogim językiem i nie ma czegoś takiego jak delegaty :)

4. Modyfikator widoczności kalsy określa widoczność tej klasy. public - można używać wszędzie, protected - tylko w obrębie paczki, private - teoretycznie klasa mogła by używać tylko samą siebie, ale z tego co wiem nie da się tak zrobić. Pola klas nie zmieniają swojej widoczności, a domyślny jest zawsze public

Jeśli nie zdefiniujemy modyfikatora dostępu dla pól klasy to nie są one domyślnie public tylko są widoczne dla klas z tego samego package.

Offline ArekBal

  • Użytkownik

# Sierpień 03, 2014, 17:12:46
Cytuj
Pola klas nie zmieniają swojej widoczności, a domyślny jest zawsze public
Cytuj
Jeśli nie zdefiniujemy modyfikatora dostępu dla pól klasy to nie są one domyślnie public tylko są widoczne dla klas z tego samego package.
Tak zwane 'package-private' by być dokładnym
Ale javowcem nie jestem

Offline LizarD

  • Użytkownik

# Sierpień 03, 2014, 19:11:01
2. Statyczne klasy składowe mają dostęp tylko do pól statycznych 'kalsy-matki', tymczasem niestatyczne klasy mają dostęp do zwykłych pól i muszą zostać stworzone poprzez instancje klasy matki. Dobrze opisuje to ten kod:
Ale po co się to robi ?

Offline Xion

  • Moderator
    • xion.log

  • +1
# Sierpień 03, 2014, 19:14:21
interface vs abstract
Ideowo, interfejs definiuje kontrakt, który klasa można spełniać, implementując go. Dzięki temu możesz być pewien, że wykazuje ona określone zachowania. W Javie sprowadza się to do określenia, jakiego typu metody dana klasa implementuje. Interfejs składa się więc z deklaracji tych metod, i niczego więcej. W szczególności: metody nie mają implementacji, a sam interfejs nie zawiera pól. (Wprawdzie interfejs w Javie może mieć publiczne stałe, ale to nie znaczy, że należy tego używać).

Przykładowe interfejsy z biblioteki standardowej: Cloneable, Closeable, Serializable, Throwable, ... Jak widać, odpowiadają one "rzeczom, które można zrobić danemu obiektowi".

Klasa abstrakcyjna to z kolei zupełnie zwyczajna klasa, poza tym że nie da się stworzyć jej obiektu -- można jedynie po niej dziedziczyć. Dlatego może ona zawierać np. stan (pola) lub kawałki logiki (metody), które będą używane przez wszystkie klasy pochodne.

Przykładowe klasy abstrakcyjne: Writer, Reader, InputStream, AbstractList, ... Jak widać, odpowiadają one ogólnym kategoriom obiektów, które mają swoje konkretne implementacje (FileReader, ArrayList, itd.)

Klasy wewnętrzne
Statyczne klasy wewnętrzne są niemal identyczne ze "zwykłymi" klasami. Jedyna różnica to to, że ich zasięg jest ograniczony do zawierającej jej klasy. Zasięg, ale nie widoczność: publiczna klasa Bar wewnątrz publicznej klasy Foo jest doskonale dostępna na zewnątrz poprzez kwalifikowaną nazwę Foo.Bar.

Niestatyczne klasy wewnętrzne mają niejawne odwołanie do `this` otaczającej klasy, co sprawia, że posiadają dostęp do jej metod i pól. To też oznacza, że da się je tworzyć wyłącznie z podaniem istniejącego obiektu klasy zewnętrznej -- zazwyczaj po prostu wewnątrz metody tej klasy.

magik6000 podał dość dobry przykład. Ogólnym zastosowaniem jest wystawienie kawałka logiki w sposób, który pozwala innym ją wywoływać. Praktyczne przykłady to:
  • listenery zdarzeń
  • kod wykonywany w specjalny sposób: w innym wątku, w transakcji, itp.

Anonimowe klasy
Ściśle związane z powyższymi. Jeśli niestatyczna klasa wewnętrzna jest krótka, czasami ma sens, żeby zdefiniować ją inline:
button.onClick(new OnClickListener() {
    @Override public void onClick(ClickEvent e) {
        MessageBox.show("Clicked");
    }
});
W większości przypadków będzie to implementacja tzw. funkcyjnego interfejsu, czyli interfejsu składającego się z tylko jednej metody. W takiej sytuacji możemy to zapisać krócej używając składni wyrażeń lambda z Javy 8:
button.onClick(e -> MessageBox.show("Clicked'));Jeśli implementacja owej jedynej metody jest dłuższa niż kilka linijek, dla czytelności dobrze jest zdefiniować anonimową klasę poza metodą, gdzie jest używana:
private OnClickListener buttonClick = new OnClickListener() {
    @Override public void onClick(ClickEvent e) {
        searchForAliens();
        foldProteins();
        proveFermatLastTheorem();
        constructWarpDrive();
    }
});

private void setupButtons() {
    // ...
    button.onClick(buttonClick);
}

Specyfikatory dostępu
Java ma cztery możliwe widoczności, i trzy słowa kluczowe do ich definiowania:
  • public (`public`) - typ/pole/metoda jest widoczny "wszędzie"
  • protected (`protected`) - typ wewnętrzny/pole/metoda jest widoczny w danej klasie, wszystkich ich klasach pochodnych, oraz w paczce zawierającej daną klasę
  • package-private (brak specyfikatora) - typ/pole/metoda jest widoczny tylko w obrębie swojej paczki
  • private (`private`) - typ wewnętrzny/pole/metoda jest widoczny tylko w klasie, w której został zdefiniowany
W przeciwieństwie np. do C++, ominięcie specyfikatora znaczy zawsze to samo: package-private. W szczególności, specyfikatory nie "kaskadują", więc w ostatnim przykładzie OP pole będzie package-private.

Offline aphity

  • Użytkownik

  • +1
# Sierpień 03, 2014, 23:06:39
(...) Przykładowe interfejsy z biblioteki standardowej: Cloneable, Closeable, Serializable, Throwable, (...)
Throwable nie jest interfejsem, tylko klasą. A poza tym wszystko się zgadza.

Offline Xion

  • Moderator
    • xion.log

# Sierpień 04, 2014, 01:11:06
Faktycznie, i to nawet konkretną klasą. Eh ta Java ;)