Kotlin tutorial #3 – loops

Pętle w programowaniu umożliwiają powtarzanie niektórych czynności. Ale nie tylko proste powtarzanie, bo to było bezsensu na dłuższą metę, ale zmianę parametrów, albo ich pobieranie, przetwarzanie według jakichś geometrycznych, lub logicznych zasad. Java posiada 3 główne (może 4, w zależności od tego jaką konwencję nazewnictwa przyjmiemy) rodzaje pętli. Kotlin jednak jak ma to w zwyczaju daje nam dużo więcej możliwości, oraz – elastyczności.

Na początek prosta pętla for, czyli iterująca liczby w zakresie od 0 do 10. W javie:

        for (int i = 0; i < 10; i++) {
            System.out.print("for1 = " + i + ", ");
        }

W Kotlinie:

    for (i in 0..10) {
        print(i)
    }

lub:

    repeat(10) {
        print("repeat10")
    }

No dobra, repeat nie jest pętlą, tylko dodaną do biblioteki standardowej metodą, ale czyż nie jest czytelniejszy? Java wymaga zdefiniowania wartości zmiennej początkowej, warunku, oraz sposobu iteracji. Część z tych elementów może oczywiście znajdować się po za pętlą for, ale nie zawsze potrzebujemy ich wszystkich. Czasem chcemy coś po prostu.. powtórzyć. 😉

Kolejnym typem pętli for jest tzw forEach, który pozwala na iterację bez użycia dodatkowej zmiennej iterującej. W javie przedstawia się tak:

        private static String[] t = {"abc", "cde", "efg"};
        for (String s : t) {
            System.out.print("for2 = " + s + ", ");
        }

Z kolei w Kotlinie:

    val list = listOf("A", "B", "C")
    for(str in list) {
        print(str)
    }

Użyłem przykładu z listą, ponieważ Kotlin nie obsługuje typów prostych, takich jak javowa tablica[].

A co jeżeli chcemy iterować po mapie? Potrzebujemy czegoś na kształt: „for (Map.Entry<String, Object> entry : map.entrySet())”. Z kolei w Kotlinie:

    val map = hashMapOf(1 to "one", 2 to "two", 3 to "three")
    for ((key, value) in map) {
        println("Map[$key] = $value")
    }

Prawda, że przyjemnie? Jest jeszcze coś fajnego, mianowicie pętle foreach możemy wywołać jak metodę, albo funkcję, bezpośrednio na obiekcie na którym operujemy. Tak to wygląda:

    map.forEach {
        print(it.key)
    }
    println()
    (1..5).forEach(::print)
    println()

Słówko kluczowe it odnosi się do bieżącego obiektu. Potrzebowaliśmy np klucza – żaden problem.

Pozostałe dwa typy pętli, które są praktycznie takie same w obydwóch językach nazywają się while i do while. Stosujemy je najczęściej wtedy, kiedy nie znamy dokładnej ilości iteracji, ale istnieje jakiś warunek który zakończy nam działanie pętli. Poniższy przykład jest taki jak w pętli for, ale nie chciałem specjalnie utrudniać, tworząc dziwne warunki, chodzi mi o sam „kształt” pętli.

        //java
        int i = 0;
        while (i < 10) {
            System.out.print("while = " + i + ", ");
            i++;
        }
        System.out.println();
        do {
            System.out.println("do while");
        } while (1 > 10);

    //kotlin
    var i = 0
    while (i < 10) {
        print("while = $i, ")
        i++
    }
    println()
    do {
        println("do while")
    } while (1 > 10)

To by było na tyle, jeśli chodzi o informacje o pętlach. Temat jeszcze powróci, kiedy będziemy omawiali lambdy 😉 Kod w aktualnej wersji znajduje się na GitHubie. Wszystkie aktualne zmiany oczywiście w pakiecie loops. W następnej części opowiem o instrukcjach sterujących w obydwóch językach.

Pozdrawiam!

— status update —

Jak widać, minęło sporo czasu, a kontynuacja kursu Kotlina się nie pojawiła. Pojawi się tutaj: https://kurskotlin.pl/ tak więc tam zapraszam #kurskotlin

Kotlin tutorial #2 – variables

Podstawą chyba każdego języka programowania są zmienne, w których można przechować wartość, którą można modyfikować. Są też stałe, kiedy nie chcemy, żeby przypadkiem coś zostało zmienione (np liczba PI, to wartość stała, nadpisywanie jej zawartości np liczbą 5 i nazywanie PI nie ma logicznych podstaw i będzie prowadzić do błędów). Java i Kotlin mają do tego aspektu podobne podejścia. Są to języki silnie, statycznie typowane, tzn jeżeli nadamy jakiś typ zmiennej, to nie da się go wprost porównać z innym typem, jeżeli np napis ma wartość 1 i zmienna typu liczbowego ma wartość 1, to one nie są sobie równe (szczegóły poniżej). Słowo statycznie oznacza z kolei, że zmienne przyjmują swoje typy w czasie kompilacji programu, a nie w czasie jego działania, jak ma to miejsce np w JavaScripcie. Kotlin posiada tutaj jednak ułatwienie, które nazywa się typowaniem zmiennych.

W praktyce oznacza to tyle, że mamy kod w javie:

        byte b = 127;
        short s = 32767;
        int i = 2147483647;
        final byte fb = 127;
        final short fs = 32767;
        final int fi = 2147483647;

Słówko final oznacza stałą, czyli po przypisaniu wartości nie można już jej zmienić. Zaprezentowane wartości to maksimum, jakie może przyjąć dana zmienna, po przekroczeniu jej zacznie się odliczanie od wartości ujemnych, coś na kształt licznika w samochodzie, tylko że tam nie ma ujemnych, tylko zero 😉 A jak to wygląda w Kotlinie?

    var c = 120
    var d: Byte = 120
    val e = 120
    //val f: String = 120

Słówko var (variables) oznacza zmienną, z kolei val (values) stałą. Druga sprawa jest taka, że na podstawie przypisanej wartości zostaje nadany odpowiedni typ zmiennej. Innymi słowy w tym przypadku domyślny będzie Int, chyba, że po dwukropku wymusimy inny typ. Kod w komentarzu się nie skompiluje, ponieważ do wprowadzania napisów (zmienna typu String) używa się dwóch znaków cudzysłowu: „120”.

W tym miejscu należy też wspomnieć o zmiennej Object w javie, po której dziedziczą wszystkie typy. Nie ma ona zbyt wielu metod, ale posiada equals – zawiera. Używamy jej do porównania zawartości obiektów.

        boolean bool = true;
        char c = 'A';
        final char e = 'E';
        String str = "Hello";
        Object ob = 1;
        int in = 1;

        for(int y = 0; y<10; y++) {
            System.out.print(c++ + " ");
            // System.out.print(e++ + " ");
            // System.out.print(ob++ + " ");
        }
        System.out.println();
        if(ob.equals(in)) {
            System.out.println(bool);
        }

Funkcja ta zwróci następujące wartości:

A B C D E F G H I J 
true

Dzieje się tak ponieważ zmienna typu char jest typem liczbowym, dzięki temu możemy zwiększając jej wartość wydrukować kolejną literę. Nie uda się to w przypadku e i ob, ponieważ jedna z nich jest stałą, druga z kolei jest typem Object, gdzie nie wiadomo jak obsługiwać iterację. Z kolei w Kotlinie:

    var c = 120
    var d: Byte = 120
    val e = 120
    //val f: String = 120
    for (i in 0..9) {
        //println(e++)
        println(c++)
    }
    println()
    for (i in 0..9) {
        println(d++)
    }
    var f = 'A'
    var g = "A"
    for (i in 0..9) {
        println(f++)
        //println(g++)
    }

Otrzymamy taką odpowiedź:

120
121
122
123
124
125
126
127
128
129

120
121
122
123
124
125
126
127
-128
-127
A
B
C
D
E
F
G
H
I
J

Co tu się stało? Po pierwsze iterujemy po c, który domyślnie został zapisany jako int, z racji wysokiego zakresu udaje nam się to bezbłędnie. Po e nie możemy iterować, ponieważ jest stała. Ale za to w zmiennej d wymuszamy typ byte, który może przyjąć wartość max 127, a następnie zaczyna iterację od najniższej wartości. Iterowanie typu char jest takie samo jak w Javie, z kolei Stringa nie można iterować, tutaj również bez niespodzianek. Słówko kluczowe equals występuje również w Kotlinie, działa tak samo jak w javie, innymi słowy porównuje wartości pomiędzy takimi samymi typami. Pojawił się też nowy operator === oznaczający, że oba obiekty mają taką samą referencję (czyli odnoszą się do tego samego obiektu). Wygląda to tak:

    var x = 1
    var y: String = "1"
    var z = x
//    if(x==y)
//        println(true)
    if(x.equals(y))
        println("x.equals(y)")
//    if(x===y)
//        println(true)
    if(x===z)
        println(true)
    if(x.equals(y.toInt()))
        println("x.equals(y.toInt())")

Co z kolei zwraca:

true
x.equals(y.toInt())

Czyli z i x mają tą samą referencję, oraz x ma taką samą wartość jak y, jeśli przekształcimy go na Int.

W podsumowaniu chciałem jeszcze zwrócić uwagę na wielkość liter. Typ zmiennej pisany z małej litery to prymityw, Kotlin już takich nie obsługuje i tam piszemy wszystko z dużej. Prymityw znaczy tyle, że nie jest obiektem, tylko typem prostym mogącym przechowywać jakąś wartość liczbową (char jest prymitywem, ponieważ przechowuje wartości liczbowe). Obiekty z kolei mają dodatkowe właściwości, mogą mieć np wartość null. Kotlin jednakże zabezpiecza nas przed taką ewentualnością.

W związku z powyższym Java posiada mechanizm automatycznego opakowywania prymitywów. Tzn, jeżeli porównujemy obiekt z prymitywem int, to automatycznie zostanie on skonwertowany do obiektu Integer o tej samej wartości. W Kotlinie z racji braku obsługi prymitywów takie operacje nie są potrzebne. To by było tyle na dzisiaj, jak widać mechanizm typowania zmiennych pozwala zaoszczędzić zbędnego kodu. Wszystkie użyte dzisiaj przykłady znajdują się też na GitHubie, zachęcam do samodzielnego pobawienia się 😉

Pozdrawiam!

— status update —

Jak widać, minęło sporo czasu, a kontynuacja kursu Kotlina się nie pojawiła. Pojawi się tutaj: https://kurskotlin.pl/ tak więc tam zapraszam #kurskotlin

Kotlin tutorial #1 – HelloWorld

Jak zapowiadałem, na blogu startuje mały kurs programowania w języku Kotlin 😉 Pomysł mam taki, żeby wrzucać tutaj kod w Javie, oraz „to samo robiący” w języku Kotlin. Co ciekawe, oba będzie można uruchomić w tym samym projekcie, ponieważ Kotlin jest językiem JVM, uruchamianym na maszynie wirtualnej Javy. Mogą nawet nawzajem korzystać ze swoich bibliotek, nawzajem się wywoływać, o czym dokładniej w następnych postach. Dodatkowo postaram się utrzymać taki poziom, żeby osoby które nie miały wcześniej styczności z programowaniem potrafiły się odnaleźć i przyswajać obydwa języki na raz. Programujących postaram się nie zanudzić i traktować Javę jako punkt odniesienia. 😉 A na początek, co to za język?

Kotlin to język programowania który jest całkiem nowy (wersja 1.0 pojawiła się 15 lutego bieżącego (2016) roku). Nazwa jak na polskie standardy nie jest zbyt szczęśliwa 🙂

kotliny

Nas oczywiście interesuje ten po lewej 🙂 Autorem języka jest firma JetBrains, tworząca oprogramowanie dla programistów, w tym między innymi środowisko IntelliJ IDEA. Skoro mamy tego samego autora IDE, oraz języka, to wiemy już gdzie jest najlepsze wsparcie 😉 Tak, zgadza się, będziemy używać Intellij (a przynajmniej ja, z ciekawostek ostatnio wylądowała wersja beta wtyczki Kotlina do NetBeans, jak ktoś lubi).

Pominę tutaj kwestię instalacji środowiska i konfiguracji Javy, ponieważ została omówiona w wielu miejscach, omawiam ją też na tym filmie. 😉 Dodatkowo na oficjalnej stronie znajduje się też świetny poradnik jak utworzyć projekt w Kotlinie. Zatem do kodu!

Poniższe metody wyświetlają po prostu napis „Hello World” na dwa różne sposoby 😉 W obydwóch językach metoda main jest miejscem w którym startuje wykonanie programu. Wygląda ona jednak nieco inaczej:

// java
public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("helloworld");
    }
}
// kotlin
fun main(args: Array<String>) {
    println("hello, world!")
}

Pierwsza różnica jest taka, że język Java potrzebuje klasy, która jest taka sama jak nazwa pliku w którym znajduje się metoda. Kotlin nie jest pod tym względem restrykcyjny. Może być klasa, o jakiejś nazwie, zupełnie niezależnej od nazwy pliku, ale nie musi być 🙂 W samej metodzie wyświetlania widać już różnicę, w Javie jest ona znacznie dłuższa, mamy tam klasę System, z obiektem out (typu PrintStream), która zawiera metodę println. W Kotlinie, mamy po prostu metodę println 🙂 Ułatwienie może wydawać się błahe, ale zawsze jest to coś, to skraca kod 🙂 Skraca go jeszcze „public static void”, z kolei w Kotlinie mamy po prostu „fun” oznaczający funkcję. Czemu to tak, napiszę wkrótce 😉 Dodatkowo, Kotlin nie potrzebuje do szczęścia średników na końcu każdej linii. Trochę późno, współczesne IDE już bardzo ładnie wyłapują takie babole, ale zawsze jest to jakieś ułatwienie 🙂

fc800x800black-u6

Po za tym jest jeszcze różnica w przekazywaniu parametrów do metody: „args: Array<String>” vs „String[] args”, ale o tym napiszę już następnym razem, kiedy będę opowiadał o zmiennych 🙂 A póki co, utworzyłem sobie te dwa pliki, jeden ma rozszerzenie java, drugi kt, obydwa da się uruchomić w jednym projekcie, klikając na zielony przycisk play, lub logo K w Intellij.

To było na tyle, jeśli chodzi o wstęp. Wszystkie przykłady znajdują się na moim GitHubie. Mam nadzieję, że ten kurs programowania Kotlin, spełni nadzieje które w nim pokładam i jak pisałem we wstępie – profesjonalistów nie zanudzi, początkującym dobrze wytłumaczy podstawy obydwóch języków 🙂 Dajcie znać jak się podoba! Następna część będzie o zmiennych, stałych, typach.. Stay tuned! 🙂

Pozdrawiam!

— status update —

Jak widać, minęło sporo czasu, a kontynuacja kursu Kotlina się nie pojawiła. Pojawi się tutaj: https://kurskotlin.pl/ tak więc tam zapraszam #kurskotlin

Week review #16 – chwila relaksu, nowe projekty, zmiany na Kenis

Kończy się tydzień numer trzydzieści siedem, który upłynął pod znakiem zbierania sił po wrocławskim devoxxie dla dzieciaków 😉 To było bardzo wyczerpujące. Ale przy tym naprawdę satysfakcjonujące 😉 Mamy wielką nadzieję, że w młodych programistach udało się zaszczepić chęć odkrywania technologii i tworzenia fajnych rzeczy 🙂 Po za tym ten tydzień był raczej nastawiony na taki reklas po urlopie i po tym wydarzeniu. Ojj powrót do pracy jest ciężki. Oto co zrobiłem w tym tygodniu.

Po pierwsze, blog się trochę zmienił 🙂 wreszcie dokończyłem moduł subskrypcji email, także śmiało można się zapisywać, albo z menu po prawej stronie, albo z pop-upa. Starałem się go ustawić tak aby był jak najmniej denerwujący, można go wyłączyć klikając gdziekolwiek na ekranie, a ciasteczka zapamiętają, żeby tak szybko ponownie się nie pojawił. Dodatkowo, edytowałem trochę kodu na stronie, w języku PHP o którym nie mam pojęcia. Bardzo pomogła mi w tym książka Gynvaela Coldwinda o nazwie „Zrozumieć programowanie”. Znajduje się tam rozdział, jak korzystając z dedukcji i tego co się umie poruszać się po językach o których nie mamy pojęcia 🙂 Przydało się, jak widać strona dalej działa, czyli pełen sukces 😉

Chciałem jeszcze w kilku słowach podsumować wydarzenie d4k. Mieliśmy z pozostałymi organizatorami w piątek spotkanie gdzie czytaliśmy feedback od kogo tylko udało się go uzyskać, a także spisywaliśmy własne uwagi, kilka rzeczy już wiemy, że zorganizujemy inaczej 🙂 Ale ogólnie odzew jest bardzo pozytywny, około 90% najwyższych ocen, czyli dzieciaki były zadowolone. A to najważniejsze, bo to dla nich organizowaliśmy wydarzenie 😉 I w przyszłym roku też zorganizujemy, niedługo znowu zaczynamy 🙂

d4k_logo

 

Noo dobrze, projekt d4k się skończył, trzeba zaczynać następne rzeczy 😉 Natura nie znosi próżni. Oto czego można się spodziewać w najbliższym czasie:

  • kanał na YT – pierwszy odcinek jest już nagrany, postanowiłem spróbować kolejnej nowej formy, zobaczymy jak mi pójdzie 🙂 został jeszcze montaż, jakieś pewnie animacje, ale o wszystkim będę tutaj informował.
  • kurs Kotlina – pomysł jest taki, aby na bieżąco porównywać go z javą i w ten sposób budować taki jak by dwujęzykowy kurs. Dla osób które znają javę – jako punkt odniesienia. Dla innych, będą mogli jednocześnie próbować zrozumieć dwa języki 🙂 Jestem bardzo ciekawy jak to wyjdzie.
  • aplikacja android + klient webowy – mam w głowie pomysł na aplikację, która rozwiązuje pewien życiowy problem, z którym wielu się boryka. Zrobiłem już mały research, były już takie aplikacje, ale żadna z nich nie miała klienta webowego. I wydaje mi się, że to była ich słabość. Jeśli się uda komercyjnie – super. Jeśli uda się mniej, będę szukał swojej szansy w następnym projekcie 😉 Wszystkie info i pewnie informacja o betatestach – pojawią się tutaj.

Po za tym serwis Kenis dla którego stworzyłem dwa kursy zmienił ich sposób dystrybucji, od tej pory kursy dostępne są w serwisie YouTube w tych dwóch playlistach:

Zachęcam również do zapoznania się z pozostałą ofertą kanału „Samuraj programowania”. Poprzednio serwis pilnował, aby lekcje wykonywać regularnie – codziennie. Teraz jest już nieco inaczej, na yt można oglądać w momencie w którym nam wygodnie. Czy to lepiej, czy gorzej, nie wiem 🙂 Faktem jest, że zapraszam do zapoznania się z nimi 🙂

To by było na tyle, jeśli chodzi o ten tydzień. Był raczej spokojny, nabrałem sił, mam wielką nadzieję, że w nadchodzącym uda mi się rozpocząć wszystkie 3 projekty o których wspomniałem. Co z tego wyjdzie, zobaczymy 😉 Stay tuned!

Pozdrawiam!

Kurs programowania android, czyli jak wzorowo się podłożyłem ;)

W swoim poprzednim poście informowałem o kursie programowania na platformę Android, który zrobiłem, dzisiaj niestety muszę napisać, że znajdował się w nim spory błąd. Wykorzystajmy to jednak, aby nauczyć się czegoś nowego 😉 Przejdę od razu do rozwiązania, w metodzie która ustawiała kolor paska na dole użyłem metody getColor() co było błędem. Metoda ta została zaimplementowana dopiero w Androidzie 6.0, z kolei do góry znajdował się warunek, jeśli wersja systemu jest większa niż 5.0. W związku z tym wszystkie lizaki miały problem z uruchomieniem aplikacji. Pierwszym rozwiązaniem o którym pomyślałem było zwiększenie warunku, jeśli wersja systemu M lub wyżej, to ustawiaj kolor paska. Ale było to jednak bez sensu, ponieważ kolor paska możemy ustawiać już w 5.0, w związku z skorzystałem z wycofanej metody: (this.getResources().getColor(R.color.colorPrimaryDark) która działa na wszystkich wersjach systemu 😉 Korzystając z okazji, że i tak dłubię w kodzie dodałem jeszcze adnotację: @TargetApi(23) metodom które podświetlały się na czerwono. One i tak były wywoływane tylko w sytuacji kiedy korzystaliśmy z Androida Marshmallow, ale w ten sposób IDE nie informuje nas, że może wystąpić w tamtym miejscu błąd.
A teraz pokażę jak doszedłem do rozwiązania tego problemu. W tym miejscu wypada podziękować użytkownikowi: „Jem ciastka”, który napisał taką opinię:

Swoją drogą, całkiem sporo możemy się dowiedzieć o użytkownikach, którzy pobrali naszą aplikację. Na początku nie bardzo uwierzyłem w to co się stało, dopóki nie zajrzałem do sekcji błędów…
Prawda, że przyjemna sekcja? 😉 Wydedukowałem o co chodzi, poprawiłem, przetestowałem na emulatorze i opublikowałem poprawkę. Cóż, popełniłem głupi błąd, za który wypada mi przeprosić. Dobrze, że instalacji jest póki co mało, dzięki temu mało osób ucierpiało. Wrzuciłem zmianę na githuba i aktualizuję aplikację w sklepie Play.
Na koniec wypada mi jeszcze napisać, cóż, błędy się zdarzają 😉 Nie warto się z tego powodu załamywać, trzeba jednak starać się za każdym razem jak najlepiej je poprawić. Nie mniej, mam nadzieję, że to jedyna poważna wtopa w tym kursie 😉
Pozdrawiam!

Różnica pomiędzy alpha a visibility dla widoków (np przycisków) w Androidzie

Widzieliście kiedyś w sklepie Play aplikację typu: odblokowywanie odciskiem palca? Z tym, że przykładaliśmy palec do ekranu? Nie trudno domyślić się sztuczki, jaka jest tam zastosowana, czyli gdzieś jest niewidoczny przycisk, po kliknięciu którego aplikacja zadziała, bądź nie. Jednakże chcąc to samemu zaimplementować można stracić trochę czasu, próbując ustawić wartość .setVisibility() na odpowiednim widoku. Do tego typu zastosowań przydaje się metoda .setAlpha() przyjmująca wartości od 0 do 255, gdzie zero oznacza całkowitą przezroczystość. No dobrze, to w takim razie do czego .setVisibility()? Przyjmuje ona 3 parametry:

View.VISIBLE;
View.INVISIBLE;
View.GONE;
Działanie pierwszego jest oczywiste, przycisk ma pozostać normalnie widoczny. Czym się różnią drugi i trzeci? W przypadku w którym zostanie wybrana niewidzialność, nasz obiekt zniknie, ale zajmowane przez niego miejsce pozostanie puste, tak jak by dalej tam był, tylko po prostu niewidzialny. Z kolei, jeśli wybierzemy View.GONE, obiekt zniknie całkowicie. Stworzyłem małe demo obrazującego jak to działa:
Jak widać, wszystkie opcje są włączone, z kolei jeśli wybierzemy GONE dla dwóch pierwszych przycisków:
Dlaczego trzeci przycisk zmienił swoją postać? Fragment xml mam nadzieję wszystko wyjaśni:


android:id=”@+id/button3″
android:layout_below=”@+id/button2″
android:layout_alignParentLeft=”true”
android:layout_alignParentStart=”true”
android:layout_alignRight=”@+id/button2″
android:layout_alignEnd=”@+id/button2″ />
Miał odnosić się do prawej strony przycisku numer dwa, a skoro nie ma przycisku numer dwa, to został mu tylko wrap_content. 
Metoda .setEnabled() jest raczej oczywista, po prostu włącz bądź wyłącz. Ciekawie robi się w sytuacji, w której połączymy ją z metodą .setAlpha(), ponieważ taka kombinacja, przy opcji visibility jako visible, powoli nam osiągnąć to, o czym pisałem we wstępie, czyli powstanie nasz ukryty przycisk. Jednakże już visibilty jako invisible, zaburzy tą konstrukcję.
Mam nadzieję, że zmieszczone tutaj informację trochę rozjaśnią problemy z dziwnym zachowaniem przycisków w niektórych sytuacjach. Stworzyłem aplikację z którą można trochę poeksperymentować i zobaczyć jak zachowają się przyciski w różnych sytuacjach. Link do repozytorium.
Pozdrawiam!

Kurs programowania java na Kenis.pl

PSsssst – poniższe informacje są już dość mocno nieaktualne, po najświeższe kursy i wszystkie poprzednie, (płatne i darmowe) zapraszam tutaj: https://kursyandroid.pl/


Każdy kiedyś zaczynał. Dlatego chciałbym podzielić się przygotowanym przeze mnie we współpracy z kenis.pl kursem programowania. Kurs jest o javie, od instalacji środowiska, przez obiektowość, kończąc na nowościach w javie 8. Kurs jest dostępny za darmo, całkowicie i absolutnie, co zresztą jest ideą Kenis, żeby wiedza była była dostępna dla każdego. Nie przedłużam i podaję link do kursu:
Kurs programowania java na Kenis.pl

Podaję jeszcze link do githuba z zadaniami:
github KenisKursJava

Zapraszam serdecznie!

Pozdrawiam!