Bir iç sınıf örneği

AbstractList sınıfı , bir Itr iç sınıfına sahiptir . Koleksiyonların öğelerini birer birer almayı mümkün kılan Iterator arayüzünün bir uygulamasıdır :


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();
	}
}

Yineleyici yönteminde kullanılır :


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

AbstractList'in soyundan gelen herhangi biri bu şekilde hazır bir yineleyici elde eder. Yineleyiciyi özelleştirmeniz gerekirse, Iterator veya Itr mirasını alan kendi sınıfınızı uygulayabilir ve ardından yineleyici yöntemini geçersiz kılabilirsiniz. Örneğin, ArrayList sınıfının yaptığı budur .

Itr sınıfı statik değildir . Sonuç olarak, Itr nesnesinin AbstractList örneğine bir referansı vardır ve yöntemlerine erişebilir ( size , get , remove ).

Statik iç içe sınıf örneği

Integer sınıfı , IntegerCache iç içe geçmiş bir sınıfa sahiptir .


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, bir önbellek oluşturan ve önbellek aralıklarının yanı sıra önbelleğe alınan değerleri depolayan işlevselliği kapsar. Böylece önbellek ile ilgili her şey ayrı bir sınıfta tutulur. Bu, kodu okumayı ve değiştirmeyi kolaylaştırır. Sınıfı kullanan kod:


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

IntegerCache sınıfı , Integer sınıfının statik olmayan alanlarına ve yöntemlerine erişmez . Ek olarak, yalnızca statik valueOf yönteminde erişilir . Yani, bireysel örneklerine değil, Tamsayı sınıfının kendisine bağlıdır . Bu da IntegerCache'in statik olduğu anlamına gelir.

Anonim bir iç sınıf örneği

Anonim bir sınıf örneği olarak, InputStream'i ve onun statik nullInputStream yöntemini ele alalım :


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;
    	}
    };
}

Yöntem , anonim bir sınıf tarafından uygulanan boş bir InputStream döndürür. Sınıfın torunları olmaması gerektiği için onu isimsiz yaptık.

Java Stream API'nin eklenmesiyle, anonim sınıflar her yerde bulunur hale geldi: tüm lambda ifadeleri, bazı işlevsel arabirimleri uygulayan anonim sınıflardır. Bazı örnekler düşünün.

AbstractStringBuilder sınıfı , ünlü StringBuilder ve StringBuffer sınıflarının ebeveynini içerir :


@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 sınıfının bir Closeable öğesini Runnable öğesine dönüştürmek için bir özelliği vardır :


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

Class sınıfı , bir yöntemin dize gösterimini almak için bir yönteme sahiptir:


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(",", "(", ")")));
}