Vlastní anotace v Javě

Anotace v Javě jsou způsobem, jak do kódu přidat meta informace (metadata, data o datech). Anotace se používají pro:

  • instrukce pro compiler
  • instrukce pro build-time
  • instrukce pro run-time

Java umožňuje vytvořit si vlastní anotace pomocí klíčového slova @interface.

@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {

	String value();
	int version() default 1; 
}

Použitá anotace @Retention(RetentionPolicy.RUNTIME) určuje, že tato anotace (@MyAnnotation) má být přístupná i v run-time. Anotace @MyAnnotation má dva elementy (value a version). Element version má nastavenu výchozí hodnotu na 1.

public @interface MyOtherAnnotation {

}

Anotace @MyAnnotation žádné elementy neobsahuje.

@MyOtherAnnotation
@MyAnnotation(value = "abcd")
public class MyClass {

}

Třída MyClass je anotována oběma anotacemi. Anotace @MyAnnotation má nastavenu hodnotu elementu value na „abcd“ a hodnotu version na 1 (default).

import java.lang.annotation.Annotation;

public class App {

	public static void main(String[] args) {
		
		Class clazz = MyClass.class;
		if (clazz.isAnnotationPresent(MyAnnotation.class)) {
			System.out.println("Je anotován: " + MyAnnotation.class.getSimpleName());
			
			MyAnnotation myAnnotation = (MyAnnotation) clazz.getAnnotation(MyAnnotation.class);
			System.out.println(myAnnotation.value());
			System.out.println(myAnnotation.version());
		}
		if (clazz.isAnnotationPresent(MyOtherAnnotation.class)) {
			System.out.println("Je anotován: " + MyOtherAnnotation.class.getSimpleName());
		}
	}
}

Výstup:

Je anotován: MyAnnotation
abcd
1

Díky tomu, že @MyAnnotation je anotováná @Retention(RetentionPolicy.RUNTIME) je možné k ní pomocí reflexe přistupovat i v run-time. Lze zjistit nejen to, zda daná třída je pomocí určité anotace anotována, ale také hodnoty elementů. Anotace @MyOtherAnnotation v runtime přítomna není.


Zdroj: tutorials.jenkov.com/java/annotations.html

Nekonečný Stream v Javě

Java 8 představila Stream, což je posloupnost hodnot, nad kterou je možné provádět operace. Je možné vytvořit i nekonečný Stream.

Stream<String> stringStream = Stream.generate(() -> UUID.randomUUID().toString());
Stream<String> constantStream = Stream.generate(() -> "word");
Stream<Double> doubleStream = Stream.generate(Math::random);
Stream<Integer> integerStream = Stream.iterate(0, (i) -> i + 1);
Stream<BigDecimal> bigDecimalStream = Stream.iterate(BigDecimal.ZERO, (bd) -> bd.add(BigDecimal.ONE));

Metoda Stream.generate() požaduje parametr typu Supplier<T>, což je funkční rozhraní obsahující metodu T get(). Metoda Stream.iterate() požaduje parametr typu T seed (počáteční element) a UnaryOperator<T>, což je funkční rozhraní dědící z funkčního rozhraní Function (místo typů <R, T> používá <T, T>, metoda apply(T) tedy nevrací typ R ale T).

Pokud nám stačí jen několik prvků streamu, můžeme použít operaci limit(n), která vezme n prvních prvků streamu.

System.out.println(Arrays.toString(stringStream.limit(5).toArray()));
System.out.println(Arrays.toString(constantStream.limit(5).toArray()));
System.out.println(Arrays.toString(doubleStream.limit(5).toArray()));
System.out.println(Arrays.toString(integerStream.limit(5).toArray()));
System.out.println(Arrays.toString(bigDecimalStream.limit(5).toArray()));

Výstup:

[cb2f9562-e468-4409-bd61-cc7f153adbc9, 45582575-fda8-48a4-9ecd-bd8e9ca87f42, 6338c4d5-7b67-4fff-b1ec-6a86e2bacec8, 9ba3c6b0-700a-4e78-b633-e6a8da9fb946, 04951054-8c43-43a6-a177-aeb2da7c7320]
[word, word, word, word, word]
[0.9250003903085224, 0.912794982359122, 0.8636553602757563, 0.5809828517176208, 0.002178508953346925]
[0, 1, 2, 3, 4]
[0, 1, 2, 3, 4]

Pozor na datový typ (na přetečení rozsahu), který je použit v nekonečném proudu.

Stream<Integer> is = Stream.iterate(1, (i) -> i * 10).limit(15);
Stream<BigDecimal> bds = Stream.iterate(BigDecimal.ONE, (bd) -> bd.multiply(new BigDecimal("10"))).limit(15);

System.out.println(Arrays.toString(is.toArray()));
System.out.println(Arrays.toString(bds.toArray()));

Výstup:

[1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000, 1410065408, 1215752192, -727379968, 1316134912, 276447232]
[1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000, 10000000000, 100000000000, 1000000000000, 10000000000000, 100000000000000]

Práce s historií v Bash

Velikost historie (počet uchovávaných příkazů) se nastavuje v souboru .bashrc v home adresáři (proměnné HISTSIZE a HISTFILESIZE). Historie v Bash se dá procházet pomocí šipek. Celou historii zobrazíme příkazem history. Výpis historie můžeme omezit přepínačem, pomocí kterého určíme, kolik příkazů z historie chceme zobrazit.

history 10 (zobrazí posledních 10 záznamů)

Pokud chceme provést nějaký příkaz z historie a nechce se nám dlouho listovat, stačí si historii zobrazit (u každého příkazu je číslo) a napsat !číslo_příkazu.

$ history
1 ls /etc
2 nano host
3 ls
4 ls -al
5 nano /etc/host
6 cd apt
7 pwd
8 cd /etc/apt
9 ls
10 nano sources.list
11 exit
12 history

V příkladu výše mám v historii celkem 12 příkazů. Pokud chci rychle provést příkaz nano /etc/host stačí mi napsat !5. Pokud chci vykonat poslední příkaz stačí napsat !!. Pro příkaz nano /etc/host jsem zapomněl uvést sudo. Stačí mi tedy napsat sudo !!.

Zdroj: digitalocean.com/community/tutorials/…

Otevření cmd ve složce

Program Příkazový řádek (cmd.exe) se dá otevřít v určité složce (programy v dané složce je možné rovnou spouštět bez zadání cesty). Otevřít v průzkumníkovi daný adresář -> stisknout klávesu Shift + pravým tlačítkem myši -> vybrat volbu „Zde otevřít příkazové okno“.

windows_otevreni_cmd

Pořadí při použití metody equals

V případě, že máme konstantu a tu porovnáváme s objektem, je vhodnější použít konstrukci konstanta.equals(objekt) než naopak. Důvod je jednoduchý. Vyhneme se tak možnosti chyby NullPointerException.

String MY_CONSTANT = "AB9922";
            
System.out.println(MY_CONSTANT.equals(MY_CONSTANT));
System.out.println(MY_CONSTANT.equals("ABCDEF"));
System.out.println(MY_CONSTANT.equals(null));

Výsledek.

true
false
false

Pokud to zkusíme opačně, kód nepůjde zkompilovat.

System.out.println(MY_CONSTANT.equals(MY_CONSTANT));
System.out.println("ABCDEF".equals(MY_CONSTANT));
// Unresolved compilation problem:  Cannot invoke equals(String) on the primitive type null
// System.out.println(null.equals(MY_CONSTANT));

Vědomě bychom konstrukci null.equals() určitě nepoužili, ale nevědomě se používá docela často. Zde je metoda, která vrací náhodný String. Vrácená hodnota tedy může být i null.

 private static String generateString() {
       int randomNumber = gen.nextInt(3);
      
       switch(randomNumber) {
              case 0:
                     return "AB9922";
              case 1:
                     return "XX8811";
              default:
                     return null;
       }
 }

Pokud budeme porovnávat objekty tímto způsobem,

 private static final String MY_CONSTANT = "AB9922";

 public static void main(String[] args) {
      
       for (int i = 0; i < 100; i++) {
              System.out.println(generateString().equals(MY_CONSTANT));
       }
 }

kód nám pravděpodobně bude nějakou chvíli fungovat, ale časem se určitě objeví NullPointerException.

true
true
false
Exception in thread "main" java.lang.NullPointerException

Předejít tomu můžeme změnou objektu, na kterém metodu equals() voláme.

for (int i = 0; i < 100; i++) {
      System.out.println(MY_CONSTANT.equals(generateString()));
}

Rychlé spuštění programu ve Windows

Operační systém Windows nabízí několik možností jak rychle spustit program (ať už pomocí klávesové zkratky či jinak). Uvádím zde několik způsobů:

Připnutí ikony programu na hlavní panel

Pravým tlačítkem na program -> Připnout na hlavní panel. Pokud z hlavního panelu chcete program odstranit, pravým tlačítkem na program na panelu -> Odepnout tento program z  hlavního panelu. Tímto způsobem je možné si upravit hlavní panel tak, aby obsahoval ty nejpoužívanější programy a ty díky tomu byly lehce přístupné.

Spuštění programu na hlavním panelu pomocí klávesové zkratky

Všechny programy připnuté k hlavnímu panelu mají své pořadové číslo (zleva doprava od jedničky). Tlačítko Start, ikona Prohledat Windows a Zobrazení úkolů se nepočítá.

windows_spusteni_programu

Na tomto snímku je můj hlavní panel. Pokud budu chtít pustit průzkumníka souborů, stisknu klávesu Windows + 1 (průzkumník Windows lze spustit i klávesovou zkratkou Win + E). Pokud budu chtít spustit Eclipse IDE, stisknu klávesu Windows + 4. Pokud program ZimNotes tak klávesu Windows + 2.

Přiřazení klávesové zkratky zástupci

Pokud máte na ploše zástupce programu, je možné mu přiřadit klávesovou zkratku. Klikněte pravým tlačítkem na ikonu programu -> Vlastnosti -> umístěte kurzor do textového pole s popiskem Klávesová zkratka a tiskněte nějaké písmeno. Automaticky se předvyplní Ctrl + Alt.

windows_spusteni_programu02

Na obrázku je programu (zástupci programu) PuTTY přiřazena klávesová zkratka Ctrl + Alt + Y.

Zdroje:

Guava Optional.orNull()

V jednom z předchozích příspěvků jsem se věnoval třídě Optional z knihovny Guava. Nezmínil jsem ale užitečnou metodu orNull(). Tato metoda buď vrátí referenci na objekt v případě, že isPresent() je true, nebo null. Může se to hodit třeba v případě, kdy ve svém kódu používáte třídu Optional, ale jiné metody požadují objekt, nebo null.

Optional str1 = Optional.of("world");
Optional str2 = Optional.absent();

System.out.println(str1.orNull());
System.out.println(str2.orNull());

Výsledek.

world
null

V následujícím kódu si všimněte metod getString01() a getString02(). Obě dělají to samé, jen getString02() je mnohem kratší a přehlednějsí.

public static void main(String[] args) {
	Optional str1 = Optional.of("world");
	Optional str2 = Optional.absent();
	
	System.out.println(getString01(str1));
	System.out.println(getString01(str2));
	System.out.println(getString02(str1));
	System.out.println(getString02(str2));
}

private static String getString01(Optional str) {
	if (str.isPresent()) {
		return str.get();
	} else {
		return null;
	}
}

private static String getString02(Optional str) {
	return str.orNull();
}

Metoda Arrays.asList()

Tato metoda vrací list fixní délky. To znamené, že jakýkoliv pokus o změnu velikosti tohoto listu skončí chybou UnsupportedOperationException.

Ať už se jedná o odebrání prvku,

List list = Arrays.asList("a", "b", "c", "b");
		
ListIterator iterator = list.listIterator();
while (iterator.hasNext()) {
	if (iterator.next().equals("b")) {
		iterator.remove();
	}
}

nebo o přidání prvku,

List list = Arrays.asList("a", "b", "c", "b");
		
ListIterator iterator = list.listIterator();
while (iterator.hasNext()) {
	if (iterator.next().equals("b")) {
		iterator.add("bbb");
	}
}

dostaneme následující chybu.

Exception in thread "main" java.lang.UnsupportedOperationException
	at java.util.AbstractList.add(AbstractList.java:148)
	at java.util.AbstractList$ListItr.add(AbstractList.java:438)
        ...

V případě, že chceme vytvořil list s proměnnou velikostí, můžeme použít parametrický konstruktor ArrayList(kolekce).

List list = new ArrayList(Arrays.asList("a", "b", "c", "b"));
		
ListIterator iterator = list.listIterator();
while (iterator.hasNext()) {
	if (iterator.next().equals("b")) {
		iterator.remove();
	}
}

Výsledkem je následující list: [a, c].

Režim celé obrazovky ve VirtualBoxu

Při vytvoření virtuálního počítače ve VirtualBoxu a instalaci operačního systému do tohoto virtuálního počítače se může stát, že zobrazení celé obrazovky nebude zcela funkční (plocha operačního systému virtuálního počítače nebude přes celé okno).

virtual_box_guest_additions

Řešením je nainstalování přídavků pro hosta (guest additions).

Zařízení -> Instalovat přídavky pro hosta.

virtual_box_guest_additions02

Zobrazí se volba co se má dělat po vložení média. Potvrdit volbu „Otevřít v souborovém manageru“.

virtual_box_guest_additions03

Dvojklikem spustit autorun.sh.

virtual_box_guest_additions04

Potvrdit spuštění souboru.

virtual_box_guest_additions05

Zadat heslo.

virtual_box_guest_additions06

Po skončení instalace stisknout Enter a operační systém ve virtuálním počítači restartovat. Po restartu by se již měla plocha operačního systému přizpůsobovat velikosti okna.

virtual_box_guest_additions07

Zdroje:

Vložení měřícího kódu

Google Analytics používá pro měření návštěvnosti webu (a další statistiky) měřící kód, který je  třeba přidat do každé stránky, která má být sledována.

Kód pro vložení lze nalézt v části „Správce“.

google_analytics_merici_kod

Následně kliknout na „Údaje o měření“ -> „Měřicí kód“.

google_analytics_merici_kod02

Nejednodušším řešením je vložit kód do části head nebo footer, která je součástí (vkládá se do) každé stránky. Ve WordPressu stačí třeba editovat soubor (vložit kód do souboru) header.php nebo footer.php, které jsou umístěny v /www/wp-content/themes/nazev_tematu.