KvCoder extends StructuredCoder<KV<K, V>> { @Override public TypeDescriptor<KV<K, V>> getEncodedTypeDescriptor() { return new TypeDescriptor<KV<K, V>>() {}.where( new TypeParameter<K>() {}, keyCoder.getEncodedTypeDescriptor()) .where(new TypeParameter<V>() {}, valueCoder.getEncodedTypeDescriptor()); } private  KvCoder(Coder<K> keyCoder, Coder<V> valueCoder); static KvCoder<K, V> of(Coder<K> keyCoder, Coder<V> valueCoder); Coder<K> getKeyCoder(); Coder<V> getValueCoder(); @Override void encode(KV<K, V> kv, OutputStream outStream); @Override void encode(KV<K, V> kv, OutputStream outStream, Context context); @Override KV<K, V> decode(InputStream inStream); @Override KV<K, V> decode(InputStream inStream, Context context); @Override List<? extends Coder<?>> getCoderArguments(); @Override void verifyDeterministic(); @Override boolean consistentWithEquals(); @Override Object structuralValue(KV<K, V> kv); @Override boolean isRegisterByteSizeObserverCheap(KV<K, V> kv); @Override void registerByteSizeObserver(KV<K, V> kv, ElementByteSizeObserver observer); @Override TypeDescriptor<KV<K, V>> getEncodedTypeDescriptor();  }
@Test public void testEncodedTypeDescriptor() throws Exception { TypeDescriptor<KV<String, Integer>> typeDescriptor = new TypeDescriptor<KV<String, Integer>>() {}; assertThat(TEST_CODER.getEncodedTypeDescriptor(), equalTo(typeDescriptor)); }