or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

advanced.mdannotations.mdcore-injection.mdindex.mdmodules.mdmultibindings.mdproviders-scopes.mdspi.mdtypes-keys.md

types-keys.mddocs/

0

# Type System & Keys

1

2

Type-safe dependency identification system supporting generic types and binding annotations for distinguishing multiple bindings of the same type.

3

4

## Capabilities

5

6

### Key Class

7

8

Identifies a dependency that can be resolved by the Injector, combining type information with optional binding annotations.

9

10

```java { .api }

11

/**

12

* Identifies a dependency that can be resolved by the Injector.

13

* A key is composed of a type and optional binding annotation.

14

* @param <T> Type of the dependency

15

*/

16

public class Key<T> {

17

/**

18

* Creates a key for the given type.

19

* @param type Class type

20

* @return Key for the type

21

*/

22

public static <T> Key<T> get(Class<T> type);

23

24

/**

25

* Creates a key for the given type with annotation type.

26

* @param type Class type

27

* @param annotationType Binding annotation type

28

* @return Key for the type with annotation

29

*/

30

public static <T> Key<T> get(Class<T> type, Class<? extends Annotation> annotationType);

31

32

/**

33

* Creates a key for the given type with annotation instance.

34

* @param type Class type

35

* @param annotation Binding annotation instance

36

* @return Key for the type with annotation

37

*/

38

public static <T> Key<T> get(Class<T> type, Annotation annotation);

39

40

/**

41

* Creates a key for the given type.

42

* @param type Type instance

43

* @return Key for the type

44

*/

45

public static Key<?> get(Type type);

46

47

/**

48

* Creates a key for the given type with annotation type.

49

* @param type Type instance

50

* @param annotationType Binding annotation type

51

* @return Key for the type with annotation

52

*/

53

public static Key<?> get(Type type, Class<? extends Annotation> annotationType);

54

55

/**

56

* Creates a key for the given type with annotation instance.

57

* @param type Type instance

58

* @param annotation Binding annotation instance

59

* @return Key for the type with annotation

60

*/

61

public static Key<?> get(Type type, Annotation annotation);

62

63

/**

64

* Creates a key for the given type literal.

65

* @param typeLiteral Type literal

66

* @return Key for the type literal

67

*/

68

public static <T> Key<T> get(TypeLiteral<T> typeLiteral);

69

70

/**

71

* Creates a key for the given type literal with annotation type.

72

* @param typeLiteral Type literal

73

* @param annotationType Binding annotation type

74

* @return Key for the type literal with annotation

75

*/

76

public static <T> Key<T> get(TypeLiteral<T> typeLiteral, Class<? extends Annotation> annotationType);

77

78

/**

79

* Creates a key for the given type literal with annotation instance.

80

* @param typeLiteral Type literal

81

* @param annotation Binding annotation instance

82

* @return Key for the type literal with annotation

83

*/

84

public static <T> Key<T> get(TypeLiteral<T> typeLiteral, Annotation annotation);

85

86

/**

87

* Returns the type literal for this key.

88

* @return TypeLiteral representing the type

89

*/

90

public TypeLiteral<T> getTypeLiteral();

91

92

/**

93

* Returns the binding annotation type, or null if none.

94

* @return Annotation type or null

95

*/

96

public Class<? extends Annotation> getAnnotationType();

97

98

/**

99

* Returns the binding annotation instance, or null if none.

100

* @return Annotation instance or null

101

*/

102

public Annotation getAnnotation();

103

104

/**

105

* Creates a new key with the same annotation but different type.

106

* @param type New type

107

* @return Key with new type

108

*/

109

public <U> Key<U> ofType(Class<U> type);

110

111

/**

112

* Creates a new key with the same annotation but different type.

113

* @param type New type

114

* @return Key with new type

115

* @since 3.0

116

*/

117

public Key<?> ofType(Type type);

118

119

/**

120

* Creates a new key with the same annotation but different type literal.

121

* @param typeLiteral New type literal

122

* @return Key with new type literal

123

* @since 3.0

124

*/

125

public <U> Key<U> ofType(TypeLiteral<U> typeLiteral);

126

127

/**

128

* Returns a new key of the same type with the specified annotation.

129

* @param annotationType Annotation type to use

130

* @return Key with specified annotation

131

* @since 5.0

132

*/

133

public Key<T> withAnnotation(Class<? extends Annotation> annotationType);

134

135

/**

136

* Returns a new key of the same type with the specified annotation.

137

* @param annotation Annotation instance to use

138

* @return Key with specified annotation

139

* @since 5.0

140

*/

141

public Key<T> withAnnotation(Annotation annotation);

142

143

/**

144

* Returns true if this key has binding annotation attributes.

145

* @return true if annotated

146

*/

147

public boolean hasAttributes();

148

149

/**

150

* Returns a key without annotation attributes.

151

* @return Key without attributes

152

*/

153

public Key<T> withoutAttributes();

154

}

155

```

156

157

**Usage Examples:**

158

159

```java

160

import com.google.inject.*;

161

import com.google.inject.name.*;

162

163

// Simple type keys

164

Key<String> stringKey = Key.get(String.class);

165

Key<DatabaseService> dbKey = Key.get(DatabaseService.class);

166

167

// Generic type keys

168

Key<List<String>> listKey = Key.get(new TypeLiteral<List<String>>() {});

169

Key<Map<String, Object>> mapKey = Key.get(new TypeLiteral<Map<String, Object>>() {});

170

171

// Keys with annotations

172

Key<String> namedKey = Key.get(String.class, Names.named("database.url"));

173

Key<Cache> primaryCache = Key.get(Cache.class, Names.named("primary"));

174

175

// Custom annotation keys

176

Key<Logger> loggerKey = Key.get(Logger.class, LoggerFor.class);

177

178

// Using keys with injector

179

DatabaseService db = injector.getInstance(Key.get(DatabaseService.class));

180

String dbUrl = injector.getInstance(Key.get(String.class, Names.named("database.url")));

181

List<String> items = injector.getInstance(Key.get(new TypeLiteral<List<String>>() {}));

182

```

183

184

### TypeLiteral Class

185

186

Represents generic types at runtime, overcoming Java's type erasure limitations.

187

188

```java { .api }

189

/**

190

* Represents a generic type T. Java doesn't yet provide a way to represent

191

* generic types, so this class does. Forces clients to create a subclass

192

* which enables retrieval of the type information even at runtime.

193

* @param <T> Generic type

194

*/

195

public class TypeLiteral<T> {

196

/**

197

* Creates a type literal for the given class.

198

* @param type Class type

199

* @return TypeLiteral for the class

200

*/

201

public static <T> TypeLiteral<T> get(Class<T> type);

202

203

/**

204

* Creates a type literal for the given type.

205

* @param type Type instance

206

* @return TypeLiteral for the type

207

*/

208

public static TypeLiteral<?> get(Type type);

209

210

/**

211

* Returns the raw (non-generic) type for this type.

212

* @return Raw type

213

*/

214

public Class<? super T> getRawType();

215

216

/**

217

* Returns the underlying Type instance.

218

* @return Type instance

219

*/

220

public Type getType();

221

222

/**

223

* Returns the generic form of supertype. For example, if this is

224

* ArrayList<String>, this returns Iterable<String> given the input Iterable.class.

225

* @param supertype a superclass of, or interface implemented by, this

226

* @return TypeLiteral for the supertype

227

* @since 2.0

228

*/

229

public TypeLiteral<?> getSupertype(Class<?> supertype);

230

231

/**

232

* Returns the resolved generic type of field.

233

* @param field a field defined by this or any superclass

234

* @return TypeLiteral for the field type

235

* @since 2.0

236

*/

237

public TypeLiteral<?> getFieldType(Field field);

238

239

/**

240

* Returns the resolved generic parameter types of methodOrConstructor.

241

* @param methodOrConstructor a method or constructor defined by this or any supertype

242

* @return List of TypeLiterals for parameter types

243

* @since 2.0

244

*/

245

public List<TypeLiteral<?>> getParameterTypes(Member methodOrConstructor);

246

247

/**

248

* Returns the resolved generic exception types thrown by methodOrConstructor.

249

* @param methodOrConstructor a method or constructor defined by this or any supertype

250

* @return List of TypeLiterals for exception types

251

* @since 2.0

252

*/

253

public List<TypeLiteral<?>> getExceptionTypes(Member methodOrConstructor);

254

255

/**

256

* Returns the resolved generic return type of method.

257

* @param method a method defined by this or any supertype

258

* @return TypeLiteral for the return type

259

* @since 2.0

260

*/

261

public TypeLiteral<?> getReturnType(Method method);

262

}

263

```

264

265

**Usage Examples:**

266

267

```java

268

import com.google.inject.*;

269

import java.util.*;

270

271

// Create type literals for generic types

272

TypeLiteral<List<String>> stringListType = new TypeLiteral<List<String>>() {};

273

TypeLiteral<Map<String, Integer>> mapType = new TypeLiteral<Map<String, Integer>>() {};

274

TypeLiteral<Set<User>> userSetType = new TypeLiteral<Set<User>>() {};

275

276

// Use with binding

277

public class CollectionModule extends AbstractModule {

278

@Override

279

protected void configure() {

280

bind(new TypeLiteral<List<String>>() {})

281

.toInstance(Arrays.asList("item1", "item2", "item3"));

282

283

bind(new TypeLiteral<Map<String, Integer>>() {})

284

.toProvider(ConfigMapProvider.class);

285

}

286

}

287

288

// Get instances using type literals

289

List<String> strings = injector.getInstance(Key.get(new TypeLiteral<List<String>>() {}));

290

Map<String, Integer> config = injector.getInstance(Key.get(new TypeLiteral<Map<String, Integer>>() {}));

291

292

// Provider methods with type literals

293

@Provides

294

List<DatabaseConnection> provideConnections() {

295

return Arrays.asList(

296

createConnection("primary"),

297

createConnection("secondary")

298

);

299

}

300

```

301

302

## Common Type Patterns

303

304

### Working with Collections

305

306

```java

307

// Binding collections

308

public class CollectionModule extends AbstractModule {

309

@Override

310

protected void configure() {

311

// Bind specific collection types

312

bind(new TypeLiteral<List<String>>() {})

313

.annotatedWith(Names.named("urls"))

314

.toInstance(Arrays.asList("http://api1.com", "http://api2.com"));

315

316

bind(new TypeLiteral<Map<String, DatabaseConfig>>() {})

317

.toProvider(DatabaseConfigProvider.class)

318

.in(Singleton.class);

319

}

320

}

321

322

// Injecting collections

323

public class ApiClient {

324

private final List<String> apiUrls;

325

private final Map<String, DatabaseConfig> dbConfigs;

326

327

@Inject

328

public ApiClient(

329

@Named("urls") List<String> apiUrls,

330

Map<String, DatabaseConfig> dbConfigs

331

) {

332

this.apiUrls = apiUrls;

333

this.dbConfigs = dbConfigs;

334

}

335

}

336

```

337

338

### Working with Wildcards

339

340

```java

341

// Wildcard type literals

342

TypeLiteral<List<? extends Animal>> animalList = new TypeLiteral<List<? extends Animal>>() {};

343

TypeLiteral<Map<String, ? super Number>> numberMap = new TypeLiteral<Map<String, ? super Number>>() {};

344

345

// Bounded type parameters

346

public class GenericService<T extends Serializable> {

347

// Implementation

348

}

349

350

// Binding generic services

351

bind(new TypeLiteral<GenericService<User>>() {})

352

.to(new TypeLiteral<UserGenericService>() {});

353

```

354

355

### Converting Between Keys and TypeLiterals

356

357

```java

358

// From TypeLiteral to Key

359

TypeLiteral<List<String>> typeLiteral = new TypeLiteral<List<String>>() {};

360

Key<List<String>> key = Key.get(typeLiteral);

361

362

// From Key to TypeLiteral

363

Key<Map<String, Object>> mapKey = Key.get(new TypeLiteral<Map<String, Object>>() {});

364

TypeLiteral<Map<String, Object>> extracted = mapKey.getTypeLiteral();

365

366

// Working with generic type information

367

Type type = typeLiteral.getType();

368

Class<?> rawType = typeLiteral.getRawType(); // Returns List.class

369

370

// Type equality

371

TypeLiteral<List<String>> type1 = new TypeLiteral<List<String>>() {};

372

TypeLiteral<List<String>> type2 = new TypeLiteral<List<String>>() {};

373

boolean equal = type1.equals(type2); // true

374

```