Guava Optional.class

Null může znamenat mnoho věcí. Aby bylo jasnější, co vlastně má null představovat, a také proto, aby uživatel ošetřil stavy, kdy může dojít k NullPointerException je tady třída Optional z knihovny Guava. Tato třída je vhodná právě pro případy, kdy null má představovat prázdnou hodnotu.

Pokud proměnná obsahuje prázdnou hodnotu (například záznam nenalezen) použije se Optional.absent(). Pokud neprázdnou hodnotu pak je to Optional, který obsahuje referenci na danou hodnotu. Pokud by v tomto případě proměnná obsahovala null, znamenalo by to, že proměnná nebyla inicializována a byla by to chyba.

Tímto způsobem je přesně řečeno, kdy proměnná něco obsahuje a kdy ne. Dalším důvodem pro tuto třídu je přimět uživatele ke kontrole, a předejít případné NullPointerException.

Hodnotu (referenci na objekt) získlám z Optional voláním metody get(). Když už voláme get(), mělo by nás trknout, že hodnota může být absent a proto bychom měli nejdříve zavolat isPresent(). Pokud tato metoda vrátí true můžeme zavolat get() a s objektem dále pracovat. Určitou nevýhodou je neustálé volání get() metody.

Třída Person.

import com.google.common.base.Optional;

public class Person {
 
       private long id;
       private String name;
       private String surname;
       private Optional<String> nickname;
      
       public Person(long id, String name, String surname) {
             this.id = id;
             this.name = name;
             this.surname = surname;
             this.nickname = Optional.absent();
       }
       public Person(long id, String name, String surname, String nickname) {
             this.id = id;
             this.name = name;
             this.surname = surname;
             this.nickname = Optional.of(nickname);
       }
      
       public long getId() {
             return id;
       }
       public void setId(long id) {
             this.id = id;
       }
       public String getName() {
             return name;
       }
       public void setName(String name) {
             this.name = name;
       }
       public String getSurname() {
             return surname;
       }
       public void setSurname(String surname) {
             this.surname = surname;
       }
       public Optional<String> getNickname() {
             return nickname;
       }
       public void setNickname(Optional<String> nickname) {
             this.nickname = nickname;
       }
}

Třída Service s metodou, která vrací Optional.absent v případě, že daný objekt Person není v seznamu nalezen. V případě, že nalezen je, vrací Optional s referencí na nalezený objekt.

import java.util.List;

import com.google.common.base.Optional;

public class Service {

	public Optional<Person> findLongInList(List<Person> list, Long id) {
		for (Person person : list) {
			if (person.getId() == id) {
				return Optional.of(person);
			}
		}
		return Optional.absent();
	}
}

Třída App, ve které je ukázána práce s Optional.

import java.util.Arrays;
import java.util.List;

import com.google.common.base.Optional;
 
public class App {
       private static List<Person> persons = Arrays.asList(
                    new Person(1L, "František", "Koudelka"),
                    new Person(2L, "John", "Smith", "johny"),
                    new Person(3L, "James", "Bond"));
 
       public static void main(String[] args) {
             Service service = new Service();
             Optional<Person> personId2 = service.findLongInList(persons, 2L);
             Optional<Person> personId3 = service.findLongInList(persons, 3L);
             Optional<Person> personId4 = service.findLongInList(persons, 4L);
 
             // Pravujeme s objektem personId2
             // Zde většinu programátorů napadně kontrola na null.
             if (personId2.isPresent()) {
                    System.out.println("Jméno člověka s id 2: " + personId2.get().getName());
                    // Je ale jednoduché zapomenout na to, že getNickname může vrátit null. S Optional je to zřejmější.
                    if (personId2.get().getNickname().isPresent()) {
                           System.out.println("Jeho přezdívka je: " + personId2.get().getNickname().get());
                    }
             }
 
             // Pravujeme s objektem personId3
             if (personId3.isPresent()) {
                    System.out.println("Jméno člověka s id 3: " + personId3.get().getName());
                    if (personId3.get().getNickname().isPresent()) {
                           System.out.println("Jeho přezdívka je: " + personId3.get().getNickname().get());
                    }
             }
 
             // Pravujeme s objektem personId4
             if (personId4.isPresent()) {
                    System.out.println("Jméno člověka s id 4: " + personId4.get().getName());
                    if (personId4.get().getNickname().isPresent()) {
                           System.out.println("Jeho přezdívka je: " + personId4.get().getNickname().get());
                    }
             }
       }
}

Po spuštění dostaneme následující výsledek:

Jméno člověka s id 2: John
Jeho přezdívka je: johny
Jméno člověka s id 3: James

Zdroje:

Testování privátních metod

V některých případech obsahuje třída složité metody, které však používá pouze tato třída a je zbytečné měnit jejich viditelnost jen kvůli otestování. K otestování takových metod je nutné využít reflexi.

Třída, kterou budeme testovat. Tato třída obsahuje veřejnou metodu compute() a privátní metodu getLongFromString(). Obě tyto metody budeme chtít otestovat.

public class MyClass {
    
    public long compute(String num1, String num2) {
          return Math.abs(getLongFromString(num1) - getLongFromString(num2));
    }

    private long getLongFromString(String number) {
          return Long.parseLong(number);
    }
}

Třída, která slouží jako předek všech testovacích tříd. Tato třída obsahuje metodu getPrivateMethods, která na základě třídy, názvu metody a jejich parametrů dokáže vrátit a zpřístupnit danou metodu na daném objektu.

import java.lang.reflect.Method;

public class AbstractTest {
 
       protected Method getPrivateMethod(Class<?> clazz, String methodName, Class<?> ... parameterTypes) {
             try {
                    // get method vrací pouze public metody
                    // Method method = clazz.getMethod(methodName, parameterTypes);
                    // proto je potřeba volat getDeclaredMethod
                    Method method = clazz.getDeclaredMethod(methodName, parameterTypes);
                    method.setAccessible(true);
                    return method;
             } catch (Exception e) {
                    throw new IllegalArgumentException("Cannot obtain method with name: " + methodName, e);
             }
       }
}

A nakonec třída s testy. Metodu getLongFromString testujeme dvakrát. Jednou pro případ, že zadáme správné parametry a podruhé testujeme, že vyhodí výjimku.

import static org.junit.Assert.assertTrue;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
 
import org.junit.BeforeClass;
import org.junit.Test;
 
public class MyClassTest extends AbstractTest {
       private static MyClass myClass;
      
       @BeforeClass
       public static void prepare() {
             myClass = new MyClass();
       }
 
       @Test
       public void computeOK() {
             String n1 = "120";
             String n2 = "330";
            
             long result = myClass.compute(n1, n2);
             assertTrue(result == 210);
       }
      
       @Test
       public void getLongFromStringOK() throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
             String n = "30";
            
             Method testedMethod = getPrivateMethod(MyClass.class, "getLongFromString", String.class);
             long result = (Long) testedMethod.invoke(myClass, n);
            
             assertTrue(result == 30);
       }
      
       @Test(expected = InvocationTargetException.class)
       public void getLongFromStringThrowsException() throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
             String s = "AB";
            
             Method testedMethod = getPrivateMethod(MyClass.class, "getLongFromString", String.class);
             testedMethod.invoke(myClass, s);
       }
      
}

Anotace @BeforeClass znamená, že daná metoda se volá jednou a to před voláním jakékoliv jiné metody ve třídě. Anotace @Test(expected = InvocationTargetException.class) definuje, jaký typ výjimky má být vyhozen. Metoda getLongFromString sice vyhodí NumberFormatException, ale ta pak způsobí InvocationTargetException. Z toho důvodu očekáváme při testu tuto výjimku.

Vytvoření řetězce z pole stringů

Níže uvedený kód předpokládá, že máme definováno následující pole: String[] arr = {"a", "b", "c", "d"}.

Použití StringBuilderu.

StringBuilder sb = new StringBuilder();
for (int i = 0; i < arr.length; i++) {
       sb.append(arr[i]);
       if (i < arr.length - 1) {
              sb.append(", ");
       }
}
System.out.println(sb.toString());

Variace na předchozí způsob.

StringBuilder sbb = new StringBuilder();
for (int i = 0; i < arr.length; i++) { 
       if (i > 0) {
              sbb.append(", ");
       }
       sbb.append(arr[i]);
}
System.out.println(sbb.toString());

Použití StringUtils (vnitřně používá StringBuilder).

String result = StringUtils.join(arr, ", ");
System.out.println(result);

Do projektu je třeba přidat závislost.

<dependency>
 <groupId>org.apache.commons</groupId>
 <artifactId>commons-lang3</artifactId>
 <version>3.4</version>
</dependency>

A trochu divoký způsob pomocí třídy Arrays a regulárních výrazů.

String string = Arrays.toString(arr);
String regex = Pattern.quote("[") + "|" + Pattern.quote("]");
String string2 = string.replaceAll(regex, "");
System.out.println(string2);

Převede pole na řetězec (ten obsahuje [] a jednotlivé stringy oddělené čárkou). Následně provede odstranění hranatých závorek. Pattern.quote() provádí správně odescapování daného znaku či sekvence znaků.

Rozdíl mezi lambda a anonymní třídou

Lambda výraz je jiný způsob zápisu anonymních tříd v Javě.

Lambda

Arrays.sort(pole, (String first, String second) -> {
	return Integer.compare(first.length(), second.length());
});

Anonymní třída

Arrays.sort(pole, new Comparator() {
	@Override
	public int compare(String first, String second) {
		return Integer.compare(first.length(), second.length());
	}
});

Lambda výraz je možné použít proto, že Comparator je funkční rozhraní. To znamená, že toto rozhraní má jedinou abstraktní metodu. Pro tato rozhraní se používá anotace @FunctionalInterface. Tato anotace není povinná a pouze kontroluje, zda dané rozhraní splňuje podmínky funkčního rozhraní.

Problém s lambda v Eclipse

Pokud používáte pro vývoj v Javě Eclipse IDE a chcete vyzkoušet psaní lambda výrazů, což je novinka v Javě 8, může se stát, že Eclipse vám validní lambda kód označí jako chybu a to i přesto, že Java 8 máte nainstalovanou a přidanou do build path. Je totiž ještě nutné nastavit compiler compliance level: Window -> Preferences -> Java -> Compiler -> vybrat „Compiler compliance level“ 1.8 -> potvrdit.

Eclipe_ide_compliance_level

Pokud ani toto nepomohlo zkontrolujte nastavení projektu: pravým na projekt -> Properties -> Java Compiler -> vybrat „Compiler compliance level“ 1.8 -> potvrdit.

Nápověda při psaní v Eclipse IDE

Pokud v Eclipse píšete kód, defaultně se nezobrazuje nápověda pro výběr. Je potřeba stisknout Ctrl a mezerník a teprve pak se obsahová nápověda zobrazí. V IntelliJ Idea IDE se rovnou při psaní nápověda, po napsání několika znaků, zobrazí.

Následující změna v nastavení Eclipse umožní automatické zobrazení kontextové nápovědy při psaní: Window -> Preferences -> Java -> Editor -> Content Assist -> v sekci „Auto Activation“ zaškrtněte „Enable auto activation“ a do „Auto activation triggers for Java:“ zadejte řetězec ._abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ a změny potvrďte.

Eclipse_content_assist

Zdroj: www.stackoverflow.com

Make, no error check v Idea IDE

V případě, že v Eclipse IDE chcete spustit main metodu v projektu, který obsahuje chyby (celý projekt nelze zkompilovat), Eclipse vás na to upozorní a zeptá se, zda chcete pokračovat. Pokud potvrdíte, že ano, zkusí pokračovat. Pokud ve spouštěné metodě a použitých třídách nemáte chybu, metoda se úspěšně spustí a vykoná.

V IntelliJ Idea IDE je tomu jinak. V případě, že projekt obsahuje chybu, nespustí se. Toto chování lze změnit: Run -> Edit Configurations … -> otevře se okno Run/Debug Configurations ->  v části „Before launch“ klikněte na plus a zvolte „Make, no error check“ -> odstraňte původní „Make“ -> OK.

Intellij_Idea_make_no_error

Zdroj: www.stackoverflow.com

Ve výše zmíněné odpovědi na Stackoverflow je uvedena i možnost změny compileru na Eclipse compiler. Tento postup mi nefungoval. Vždy bylo ještě potřeba změnit Run/Debug Configuration na „Make, no error check“.

Rozšíření funkčnosti editoru ve WordPressu

Editor článků a příspěvků TinyMCE je dostatečný, avšak časem určitě narazíte na funkcionality, které mu chybí. U mě to byla chybějící volba pro přidání tabulky. Editor tuto možnost má, ale defaultně není zobrazena. Jedním z řešení je instalace TinyMCE Advanced pluginu, který tyto volby zpřístupní.

tinymce_advanced

Následujícím způsobem pak po instalaci pluginu bude vypadat menu TinyMCE editoru.

tinymce_advanced02

Řešení jsem našel na tomto webu: www.mujitblog.cz

Přihlášení do Windows 10 bez zadání hesla

V případě, že nechcete při každém spuštění počítače s Window 10 zadávat přihlašovací údaje, můžete si nastavit automatické přihlašování. Klikněte na lupu („Prohledat Windows“) v levé části panelu nástrojů a do ní zadejte netplwiz  a spusťte příkaz (netplwiz.exe je umístěn v adresáři C:\Windows\System32 a slouží pro spravování uživatelských účtů).

lupa

Otevře se vám okno „Uživatelské účty“. V něm zrušte volbu pro zadávání přihlašovacích údajů a potvrďte.

uzivatelske_ucty

Po potvrzení se otevře další okno, kde zadáte uživatele, který bude automaticky přihlášen.

Pozor, tento postup mi nefungoval v případě, že jsem se snažil přihlásit účtem Microsoft. Je nutné se přihlašovat místním účtem. Klikněte na lupu a napište uživatelské účty . Otevře se vám okno „Uživatelské účty“. V něm klikněte na „Provést změny mého účtu v nastavení počítače“. Zde si vytvořte místní účet a nastavte přihlašování pomocí místního účtu.