JavaRush /Курсы /Модуль 2. Java Core /Примеры разных типов классов из JDK

Примеры разных типов классов из JDK

Модуль 2. Java Core
15 уровень , 3 лекция
Открыта

Пример внутреннего класса

В классе AbstractList есть внутренний класс Itr. Это реализация интерфейса Iterator, который позволяет поочередно получать элементы коллекций:


private class Itr implements Iterator<E> {
	int cursor = 0;
	int lastRet = -1;
	int expectedModCount = modCount;
 
	public boolean hasNext() {
    		return cursor != size();
	}
 
	public E next() {
    	checkForComodification();
    	try {
        	int i = cursor;
        	E next = get(i);
        	lastRet = i;
        	cursor = i + 1;
        	return next;
    	} catch (IndexOutOfBoundsException e) {
        	checkForComodification();
        	throw new NoSuchElementException(e);
    	}
	}
 
	public void remove() {
    	if (lastRet < 0)
        	throw new IllegalStateException();
    	checkForComodification();
 
    	try {
        	AbstractList.this.remove(lastRet);
        	if (lastRet < cursor)
            	cursor--;
        	lastRet = -1;
        	expectedModCount = modCount;
    	} catch (IndexOutOfBoundsException e) {
   	     throw new ConcurrentModificationException();
    	}
	}
 
	final void checkForComodification() {
    	if (modCount != expectedModCount)
        	throw new ConcurrentModificationException();
	}
}

Используется он в методе iterator:


public Iterator<E> iterator() {
	return new Itr();
}

Таким образом любой класс-наследник AbstractList получает готовый рабочий итератор. А если нужно все-таки кастомизировать итератор, можно реализовать свой класс, унаследовав его от Iterator или Itr, и переопределить метод iterator. Например, как это сделано в классе ArrayList.

Класс Itr — нестатический. Благодаря этому у экземпляра Itr есть ссылка на экземпляр AbstractList, и он может обращаться к его методам (size, get, remove).

Пример внутреннего статического класса

В классе Integer есть внутренний класс IntegerCache:


private static class IntegerCache {
	static final int low = -128;
	static final int high;
	static final Integer[] cache;
	static Integer[] archivedCache;
 
	static {
    	int h = 127;
    	String integerCacheHighPropValue =
        	VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
    	if (integerCacheHighPropValue != null) {
        	try {
            	h = Math.max(parseInt(integerCacheHighPropValue), 127);
            	h = Math.min(h, Integer.MAX_VALUE - (-low) -1);
        	} catch( NumberFormatException nfe) {
        	}
    	}
    	high = h;
 
    	VM.initializeFromArchive(IntegerCache.class);
    	int size = (high - low) + 1;
 
    	if (archivedCache == null || size > archivedCache.length) {
        	Integer[] c = new Integer[size];
        	int j = low;
        	for(int i = 0; i < c.length; i++) {
            	c[i] = new Integer(j++);
        	}
        	archivedCache = c;
    	}
    	cache = archivedCache;
    	assert IntegerCache.high >= 127;
}
 
	private IntegerCache() {}
}

IntegerCache инкапсулирует в себе генерацию кеша, хранит диапазона кеша и сами закешированные значения. Таким образом все, что касается кеша, вынесено в отдельный класс. Это упрощает чтение кода и внесение в него изменений. Код использования класса:


public static Integer valueOf(int i) {
	if (i >= IntegerCache.low && i <= IntegerCache.high)
    		return IntegerCache.cache[i + (-IntegerCache.low)];
	return new Integer(i);
}

Класс IntegerCache не обращается к нестатическим полям и методам класса Integer, а обращение к нему происходит только в статическом методе valueOf. То есть можно сказать, что он привязан ко всему классу Integer, а не к отдельным его экземплярам, — и поэтому IntegerCache статический.

Пример внутреннего анонимного класса

В качестве примера анонимного класса возьмем класс InputStream и его статический метод nullInputStream:


public static InputStream nullInputStream() {
    return new InputStream() {
    	private volatile boolean closed;
 
    	private void ensureOpen() throws IOException {
        	if (closed) {
            		throw new IOException("Stream closed");
        	}
    	}
 
    	@Override
    	public int available () throws IOException {
        	ensureOpen();
        	return 0;
    	}
 
    	@Override
    	public int read() throws IOException {
        	ensureOpen();
        	return -1;
    	}
 
    	@Override
    	public int read(byte[] b, int off, int len) throws IOException {
        	Objects.checkFromIndexSize(off, len, b.length);
        	if (len == 0) {
            		return 0;
        	}
        	ensureOpen();
        	return -1;
    	}
 
    	@Override
    	public byte[] readAllBytes() throws IOException {
        	ensureOpen();
        	return new byte[0];
    	}
 
    	@Override
    	public int readNBytes(byte[] b, int off, int len)throws IOException {
        	Objects.checkFromIndexSize(off, len, b.length);
        	ensureOpen();
        	return 0;
    	}
 
    	@Override
   	 public byte[] readNBytes(int len) throws IOException {
        	if (len < 0) {
            		throw new IllegalArgumentException("len < 0");
        	}
        	ensureOpen();
        	return new byte[0];
    	}
 
    	@Override
    	public long skip(long n) throws IOException {
        	ensureOpen();
        	return 0L;
    	}
 
    	@Override
    	public void skipNBytes(long n) throws IOException {
        	ensureOpen();
        	if (n > 0) {
            		throw new EOFException();
        	}
    	}
 
    	@Override
    	public long transferTo(OutputStream out) throws IOException {
        	Objects.requireNonNull(out);
        	ensureOpen();
        	return 0L;
    	}
 
    	@Override
    	public void close() throws IOException {
        	closed = true;
    	}
    };
}

Метод возвращает пустой InputStream, а для его реализации как раз используется анонимный класс. Так как у класса не предполагались наследники, его сделали анонимным.

С добавлением в Java Stream API анонимные классы стали использовать повсеместно: все лямбда-выражения — это анонимные классы, реализующие тот или иной функциональный интерфейс. Рассмотрим примеры.

В классе AbstractStringBuilder — родитель знаменитых StringBuilder и StringBuffer:


@Override
public IntStream chars() {
	return StreamSupport.intStream(
        	() -> {
            	byte[] val = this.value;
            	int count = this.count;
            	byte coder = this.coder;
            	return coder == LATIN1
                   	? new StringLatin1.CharsSpliterator(val, 0, count, 0)
                   	: new StringUTF16.CharsSpliterator(val, 0, count, 0);
        	},
        	Spliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED,
        	false);
}

В классе Files — метод для конвертации Closeable в Runnable:


private static Runnable asUncheckedRunnable(Closeable c) {
	return () -> {
    	try {
        	c.close();
    	} catch (IOException e) {
        	throw new UncheckedIOException(e);
    	}
	};
}

В классе Class — метод для строкового отображения метода:


private String methodToString(String name, Class<?>[] argTypes) {
	return getName() + '.' + name +
        	((argTypes == null || argTypes.length == 0) ?
        	"()" :
        	Arrays.stream(argTypes)
        	        .map(c -> c == null ? "null" : c.getName())
                	.collect(Collectors.joining(",", "(", ")")));
}
Комментарии (8)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
17 октября 2025
Эта лекция для кого предназначена? Зачем здесь вообще такое выкладывать?
Ardan Уровень 57
13 июня 2025
Освежили память чуть чуть узнали нового в коде разбираться тяжело понял только что там методы примерно знаю что они делают информация очень убивает хахха
Денис Уровень 68
16 марта 2025
Очень фраппирует данный поток мыслей..
Булат Уровень 109
3 ноября 2024
хаах) чисто набор букв) глазами пробежался, мгм, хоть бы 5% понять что здесь)
Dmytryi Shubchynskyi Уровень 111 Expert
21 сентября 2022
Все предельно ясно
Владимир Чугуевец Уровень 108 Expert
22 июля 2022
Надеюсь эта лекция для нас в будущем, когда мы будем уже Senior. Чтобы вернутся сюда и понять, что тут написано.
Константин Уровень 100 Expert
24 июля 2022
Я думаю здесь информация дана для ознакомления, когда придет время все поймешь)
Владимир Уровень 109 Expert
29 июня 2022