## Описатели ограничения доступа
- `public` - элемент доступен без всяких ограничений
- `private` - доступ разрешен только из данного класса
- `protected` - доступ разрешен из данного класса, из всех классов-потомков и из всех классов данного пакета
- **Без описателя** - доступ разрешен из всех классов данного пакета
## Некоторые важные пакеты Java
- `java.lang` - базовый пакет языка Java
- `java.io` - пакет поддержки ввода-вывода
- `java.util` - классы поддержки коллекций объектов, работы с календарем и т. д.
- `java.awt` - базовый пакет поддержки визуальных приложений
- `javax.swing` - пакет визуального программирования. Появился в Java 2
- `java.applet` - пакет поддержки создания апплетов
```java
package mypack;

public class Anna {
	String name;
	int number;
	
	public String getName() {
		return name;
	}
	
	public String getNumber() {
		return number;
	}
	
	public void setName(String valueName) {
		name = valueName;
	}
	
	public void setNumber(String valueNumber) {
		number = valueNumber;
	}
	
	@Override
	public String toString() {
		return "Anna{" +
			"name='" + name + '\'' +
			", number=" + number +
			'}'
	}
}

public class Main {
	public static void main(String[] args) {
		Anna ann = new Anna();
		ann.setName("Староста");
		ann.setNumber(666);
		System.out.print(ann);
	}
}
```
## Спецификатор `static`
Для поля `static` означает, что оно создается в единственном экземпляре. Даже если ни одного объекта класса не было создано, поле существует. По отношению к функциям примерно то же самое - статический метод не связан ни с одним объектом. Его можно вызывать через имя класса. Внутри такого метода нельзя обращаться к нестатическим полям и методам класса без указания имени объекта. 
## Наследование классов
```java
class A {
	// тело класса А
}

class B extends A {
	// тело класса B
}
```
Множественное наследование в Java запрещено.
```java
package mypack;

public class Anna {
	String name;
	
	public String getName() {
		return name;
	}
	
	public void setName(String valueName) {
		name = valueName;
	}
	
	public Anna(String name) {
		this.name = number;
	}
}

public class Egor extends Anna {
	int number;
	
	public Egor(String name, int number) {
		super(name);
		this.number = number;
	}

	public String getNumber() {
		return number;
	}
	
	public void setNumber(String valueNumber) {
		number = valueNumber;
	}
}

public class Main {
	public static void main(String[] args) {
		Anna ann = new Anna("Староста_1");
		System.out.println(ann);
		Egor eg = new Egor("Староста_2", 777);
		System.out.println(eg);
		Anna aa = eg;
		System.out.println(eg);
	}
}
```
## Полиморфизм
#### Overloading - совместное использование
```java
class X {
	int f() {
		...
	}
	void f(int k) {
		...
	}
	...
}
```
  
```java
class Base {
	int f(int k) {
		...
	}
	...
}

class Derived extends Base {
	int f(String s, int k) {
		...
	}
	...
}
```
#### Overriding - переопределение
```java
class Base {
	int f(int k) {
		...
	}
	...
}

class Derived extends Base {
	int f(int k) {
		...
	}
	...
}
```
  
```java
public class Anna {
	...
	public void print() {
		System.out.println("Anna");
}

public class Egor {
	...
	public void print() {
		System.out.println("Egor");
}

public class Main {
	public static void main(String[] args) {
		Anna ann = new Anna("Староста_1");
		ann.print();
		Egor eg = new Egor("Староста_2", 777);
		eg.print();
	}
}
```
## Ключевое слово `final`
Ключевое слово `final` используется для описания полей, методов и классов. В отношении полей, переменных и параметров это константа. В сочетании со `static`, `final` дает глобальную константу. Метод, описанный с `final`, не может быть переопределен в классе-наследнике. Класс с `final` не может наследоваться.
## Абстрактные классы
```java
public abstract class D {
	int g1(int s) {
		...
	}
	
	public abstract void g2(String str);
}
```
  
```java
public abstract class Anna {
	...
	public abstract void print();
```
## Интерфейсы
**Интерфейс** изначально был задуман как полностью абстрактный класс, не содержащий никаких полей кроме `static final`. Говорят, что один класс наследует другой, но реализует (`implements`) интерфейс. Поскольку интерфейс - полностью абстрактный класс, для интерфейсов допустимо множественное наследование
```java
public interface XXX {
	...
	int f(String s);
}

public interface YYY {
	...
	int g(String s);
}

public class R implements XXX, YYY {
	...
	public int f(String s) {...}
	public int g(String s) {...}
	...
}
```
## Вложенные классы
Класс может быть вложен в другой класс или метод другого класса.
```java
public class Outer {
	int y;
	Outer(int x) {
		y = x;
	}
	
	class Inner1 { // Вложенный класс. Размещен внутри класса Outer
		int g(String s) {
			class Inner2 { // Вложенный класс. Размещен внутри метода g класса Outer
				...
			}
			...
		}
		...
	}
	...
}
```
При компиляции Java сформирует 3 файла: файлы для классов `Outer`, `Inner1` и `Inner2`. Для вложенных классов вида `Inner1` имеют смысл спецификаторы `private` и `protected`. Класс `Inner2` виден только внутри метода. Внутри класса `Outer` объекты класса `Inner1` создаются обычным образом. Вне класса `Outer` для создания объекта `Inner1` нужно, чтобы существовал объект класса `Outer`.
#### Анонимные вложенные классы
В ряде случаев удобно использовать класс без имени - **анонимный класс**. Если класс анонимный, то он всегда вложенный. Использование анонимных вложенных классов позволяет уменьшить размер кода.
```java
public static void main(String[] args) {
	List list = new ArrayList();
	list.add(new Integer(123));
	list.add(new Integer(12));
	list.add(new Integer(23));
	list.add(new Integer(1123));
	list.add(new Integer(3));
	System.out.println(list);
	Comparator Vlad = new Comparator() {
		@Override
		public int compare(Object o1, Object o2) {
			int a = ((Integer)o1).intValue();
			int b = ((Integer)o2).intValue();
			return a < b ? 1 : a == b ? 0 : -1;
		}
	}
	Collections.sort(list, Vlad)
	System.out.println(list);
}
```
  
```java
Collections.sort(list, new Comparator() {
		@Override
		public int compare(Object o1, Object o2) {
			int a = ((Integer)o1).intValue();
			int b = ((Integer)o2).intValue();
			return a < b ? 1 : a == b ? 0 : -1;
		}
	});
```
  
```java
public static void main(String[] args) {
	List list = new ArrayList();
	String s = "Vlad";
	list.add(new Integer(123));
	list.add(new Integer(12));
	list.add(new Integer(23));
	list.add(new Integer(1123));
	list.add(new Integer(3));
	list.add(s);
	System.out.println(list);
	Collections.sort(list, new Comparator() {
		@Override
		public int compare(Object o1, Object o2) {
			int a = ((Integer)o1).intValue();
			int b = ((Integer)o2).intValue();
			return a < b ? 1 : a == b ? 0 : -1;
		}
	});
	System.out.println(list);
}
```
## Дженерики
**Дженерики (обобщения)** - особые средства языка Java для реализации обобщенного программирования: особого подхода к описанию данных и алгоритмов, позволяющего работать с различными типами данных без изменения их описания. Дженерики появились в Java 5.0.
```java
public static void main(String[] args) {
	List<Integer> list = new ArrayList<Integer>();
	list.add(123);
	list.add(12);
	list.add(23);
	list.add(1123);
	list.add(3);
	System.out.println(list);
	Collections.sort(list, new Comparator() {
		@Override
		public int compare(Object o1, Object o2) {
			int a = ((Integer)o1).intValue();
			int b = ((Integer)o2).intValue();
			return a < b ? 1 : a == b ? 0 : -1;
		}
	});
	System.out.println(list);
}
```