Rozdíl mezi rozhraním a statickou třídou v Javě

Java 8 zavedla defaultní metody v rozhraní, čímž trochu smyla rozdíl mezi rozhraním a abstraktní třídou. V tomto příspěvku se tedy podíváme blíže na rozhraní, jejich defaultní metody, abstraktní třídy a rozdíly mezi rozhraními a abstraktními třídami. Defaultním metodám se věnoval i tento dřívější příspěvek.

Rozhraní:
Může obsahovat statické metody.
Může obsahovat metody, které jsou implementovány (mají tělo).
Pro implementaci rozhraní se používá klíčové slovo implements.
Rozhraní nemůže mít instanční proměnné.
Rozhraní může mít pouze proměnné typu public static final (konstanty).
Metody v rozhraní jsou defaultně public abstract.

Číst dálRozdíl mezi rozhraním a statickou třídou v Javě

Změna verze Javy z 8 na 11

Nedávno jsem prováděl změny verze Javy na projektu, který používá Spring Boot. Měnil jsem verzi Javy z verze 8 na verzi 11. Nebylo to až tak strašné, jak jsem čekal (spíše naopak), přesto se ale některé komplikace objevily. V tomto příspěvku budu postupovat od chyby k chybě, tak jak se u mě objevovaly.

Číst dálZměna verze Javy z 8 na 11

Proudy v Java 8

Proudové (stream) zpracovávání je novinka Javy 8. Cílem je zjednodušit operace nad posloupnostmi prvků. Umožňují zřetězení operací. Operace se dělí do dvou hlavních skupin:

  • terminální (terminal) – touto operací je proud uzavřen
  • neterminální (intermediate) – vytváří nový proud

Jak je vidět z popisu, neterminální operace lze za sebou řetězit, dokud se nezavolá operace terminální.

Nejpoužívanější operace jsou

forEach terminální všechny prvky proudu postupně odešle konzumentovi
findFirst terminální vrátí první prvek pokud existuje
collect terminální sesbírá elementy a vytvoří z nich návratovou strukturu
map neterminální převede prvky na jiné
filter neterminální filtruje podle zadaného predikátu (podmínky)
sorted neterminální seřadí prvky

Příklady použití.

Číst dálProudy v Java 8

Rozhraní a defaultní metody v Javě

Defaultní metody v rozhraní nám umožňují přidávat do rozhraní nové metody bez toho, abychom rozbili původní kód. Zde je jednoduchý příklad.

rozhraní MyIntf.java

public interface MyIntf {
	void print(String text);
}

implementace MyIntfImpl.java

public class MyIntfImpl implements MyIntf {

	@Override
	public void print(String text) {
		System.out.println("Printing: " + text);
	}
}

Číst dálRozhraní a defaultní metody v Javě

Java 8 – filter a map

Java 8 představila streamy a ty mají různé metody. V tomto příspěvku si ukážeme použití metod filter a map. Z původního seznamu se nejdříve vyfiltrují položky, které mají (present) status a vrátí se nový seznam, který obsahuje tyto statusy.

import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

public class App2 {

	public static void main(String[] args) {
		List<MO> list = Arrays.asList(
				new MO(Optional.of(Status.CLOSED.getId()), "AAA"),
				new MO(Optional.of(Status.OPEN.getId()), "BBB"),
				new MO(Optional.empty(), "CCC"),
				new MO(Optional.empty(), "DDD"),
				new MO(Optional.of(Status.OPEN.getId()), "EEE")
		);

		List<Long> open = list.stream()
			.filter(myObject -> myObject.getStatus().isPresent())
			.map(myObject -> myObject.getStatus().get())
			.collect(Collectors.toList());

		open.forEach(System.out::println);
	}

	private enum Status {
		OPEN(1L), CLOSED(2L);

		private long id;

		private Status(long id) {
			this.id = id;
		}

		public long getId() {
			return id;
		}
	}
}
 class MO {

	private Optional<Long> status;
	private String name;

	public MO(Optional<Long> status, String name) {
		this.status = status;
		this.name = name;
	}

	public Optional<Long> getStatus() {
		return status;
	}

	public void setStatus(Optional<Long> status) {
		this.status = status;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
}

Výsledek:

2
1
1

Filtrování v Java 8

Java 8 představila streamy a ty mají metodu filter, která má jako parametr predikát (funkce vracejítí pravdu nebo nepravdu). V následujícím příkladu se z původního seznamu vytvoří nový seznam, který bude obsahovat pouze objekty se statusem OPEN.

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class App {

	public static void main(String[] args) {
		List<MyObject> list = Arrays.asList(
				new MyObject(Status.CLOSED.getId(), "AAA"),
				new MyObject(Status.OPEN.getId(), "BBB"),
				new MyObject(Status.OPEN.getId(), "CCC"),
				new MyObject(Status.CLOSED.getId(), "DDD"),
				new MyObject(Status.OPEN.getId(), "EEE")
		);

		List<MyObject> open = list.stream()
			.filter(myObject -> myObject.getStatus() == Status.OPEN.id)
			.collect(Collectors.toList());

		open.forEach(openObject -> System.out.println(openObject.getName()));
	}

	private enum Status {
		OPEN(1L), CLOSED(2L);

		private long id;

		private Status(long id) {
			this.id = id;
		}

		public long getId() {
			return id;
		}
	}
}
 class MyObject {

	private long status;
	private String name;

	public MyObject(long status, String name) {
		this.status = status;
		this.name = name;
	}

	public long getStatus() {
		return status;
	}

	public void setStatus(long status) {
		this.status = status;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
}

Výsledek:

BBB
CCC
EEE

Nastavení JAVA_HOME v Ubuntu

Proměnnou JAVA_HOME nastavíme tak, že si otevřeme soubor /etc/environment a do něj vložíme záznam:

JAVA_HOME="/usr/lib/jvm/java-8-oracle"

Soubor environment znovu načteme:

source /etc/environment

To, že naše proměnná je funkční můžeme otestovat výpisem do konzole:

echo $JAVA_HOME
/usr/lib/jvm/java-8-oracle

Zdroj: askubuntu.com/…/how-to-set-java-home-for-java

Instalace Java 8 na Ubuntu

Nejdříve je nutné přidat repozitář do souboru /etc/apt/sources.list příkazem add-apt-repository:

vitfo@vitfo-VirtualBox:/etc/opt/hbase-1.2.6$ sudo add-apt-repository ppa:webupd8team/java
[sudo] password for vitfo: 
 Oracle Java (JDK) Installer (automatically downloads and installs Oracle JDK7 / JDK8 / JDK9). There are no actual Java files in this PPA.

Important -> Why Oracle Java 7 And 6 Installers No Longer Work: http://www.webupd8.org/2017/06/why-oracle-java-7-and-6-installers-no.html

Ubuntu 16.10 Yakkety Yak is no longer supported by Canonical (and thus, Launchpad and this PPA). The PPA supports Ubuntu 17.10, 17.04, 16.04, 14.04 and 12.04.

More info (and Ubuntu installation instructions):
- for Oracle Java 7: http://www.webupd8.org/2012/01/install-oracle-java-jdk-7-in-ubuntu-via.html
- for Oracle Java 8: http://www.webupd8.org/2012/09/install-oracle-java-8-in-ubuntu-via-ppa.html

Debian installation instructions:
- Oracle Java 7: http://www.webupd8.org/2012/06/how-to-install-oracle-java-7-in-debian.html
- Oracle Java 8: http://www.webupd8.org/2014/03/how-to-install-oracle-java-8-in-debian.html

Oracle Java 9 (for both Ubuntu and Debian): http://www.webupd8.org/2015/02/install-oracle-java-9-in-ubuntu-linux.html

Oracle JDK 9 is now considered stable. There are currently only 64bit builds (no other builds are available for download: http://www.oracle.com/technetwork/java/javase/downloads/index.html )
 More info: https://launchpad.net/~webupd8team/+archive/ubuntu/java
Press [ENTER] to continue or ctrl-c to cancel adding it

gpg: keyring `/tmp/tmpcs1we49p/secring.gpg' created
gpg: keyring `/tmp/tmpcs1we49p/pubring.gpg' created
gpg: requesting key EEA14886 from hkp server keyserver.ubuntu.com
gpg: /tmp/tmpcs1we49p/trustdb.gpg: trustdb created
gpg: key EEA14886: public key "Launchpad VLC" imported
gpg: no ultimately trusted keys found
gpg: Total number processed: 1
gpg:               imported: 1  (RSA: 1)
OK

Aktualizovat (update) informace o balíčcích příkazem apt update:

Číst dálInstalace Java 8 na Ubuntu

Porovnávání Optional

Při porovnávání Optional není nutné kontrolovat isPresent a volat hodnotu, ale jde rovnou porovnánat objekty.

Optional<Long> emptyLong = Optional.empty();
Optional<Long> l1 = Optional.of(1L);
Optional<String> s1 = Optional.of("abc");

System.out.println(emptyLong.equals(l1));
System.out.println(emptyLong.equals(Optional.empty()));
System.out.println(l1.equals(s1));
System.out.println(s1.equals(Optional.of("abc")));

Výsledek

false
true
false
true

Stejné to je v testech (např. při použití testNG):

assertNotEquals(emptyLong, l1);
assertEquals(emptyLong, Optional.empty());
assertNotEquals(l1, s1);
assertEquals(s1, Optional.of("abc"));

Takto asserty projdou. Pokud bychom to změnili např. na assertEquals(emptyLong, l1), dostali bychom následující chybu:

Exception in thread "main" java.lang.AssertionError: expected [Optional[1]] but found [Optional.empty]
	at org.testng.Assert.fail(Assert.java:93)
	at org.testng.Assert.failNotEquals(Assert.java:512)
	at org.testng.Assert.assertEqualsImpl(Assert.java:134)
	at org.testng.Assert.assertEquals(Assert.java:115)
	at org.testng.Assert.assertEquals(Assert.java:178)
	at ...