{"id":13485958,"url":"https://github.com/jhalterman/typetools","last_synced_at":"2025-05-14T22:09:12.754Z","repository":{"id":46931725,"uuid":"1019228","full_name":"jhalterman/typetools","owner":"jhalterman","description":"Tools for working with generic types","archived":false,"fork":false,"pushed_at":"2023-04-12T01:45:16.000Z","size":324,"stargazers_count":631,"open_issues_count":23,"forks_count":93,"subscribers_count":24,"default_branch":"master","last_synced_at":"2025-05-09T18:54:02.130Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jhalterman.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGES.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2010-10-24T07:11:54.000Z","updated_at":"2025-05-04T03:53:12.000Z","dependencies_parsed_at":"2024-01-03T01:21:59.388Z","dependency_job_id":"151d2033-c052-480e-9006-120a644d19d5","html_url":"https://github.com/jhalterman/typetools","commit_stats":null,"previous_names":[],"tags_count":18,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jhalterman%2Ftypetools","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jhalterman%2Ftypetools/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jhalterman%2Ftypetools/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jhalterman%2Ftypetools/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jhalterman","download_url":"https://codeload.github.com/jhalterman/typetools/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254235701,"owners_count":22036964,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-07-31T18:00:35.055Z","updated_at":"2025-05-14T22:09:07.740Z","avatar_url":"https://github.com/jhalterman.png","language":"Java","readme":"# TypeTools\n\n[![Build Status](https://github.com/jhalterman/typetools/workflows/build/badge.svg)](https://github.com/jhalterman/typetools/actions)\n[![Maven Central](https://img.shields.io/maven-central/v/net.jodah/typetools.svg?maxAge=60\u0026colorB=53C92E)](https://maven-badges.herokuapp.com/maven-central/net.jodah/typetools)\n[![License](http://img.shields.io/:license-apache-brightgreen.svg)](http://www.apache.org/licenses/LICENSE-2.0.html)\n[![JavaDoc](https://img.shields.io/maven-central/v/net.jodah/typetools.svg?maxAge=60\u0026label=javadoc\u0026color=blue)](https://jodah.net/typetools/javadoc/)\n\nA simple, zero-dependency library for working with types. Supports Java 1.6+ and Android.\n\n## Introduction\n\nOne of the sore points with Java involves working with type information. In particular, Java's generics do not provide a way to resolve or reify the type information for a given class. TypeTools looks to solve this by fully resolving generic type information declared on any class, interface, lambda expression or method.\n\n## Usage\n\nThe [TypeResolver](http://jodah.net/typetools/javadoc/net/jodah/typetools/TypeResolver.html) class provides some of the following methods:\n\n* `Type reify(Type type, Class\u003cS\u003e context)`\n\u003cbr\u003eReturns a fully reified `type` using type variable information from the `context`.\n* `Type reify(Type genericType)`\n\u003cbr\u003eReturns a fully reified `genericType` using information from the generic declaration.\n* `Class\u003c?\u003e[] resolveRawArguments(Class\u003cT\u003e type, Class\u003cS\u003e subType)`\n\u003cbr\u003eResolves the raw arguments for a `type` using type variable information from a `subType`.\n* `Class\u003c?\u003e resolveRawArgument(Class\u003cT\u003e type, Class\u003cS\u003e subType)`\n\u003cbr\u003eResolves the raw argument for a `type` using type variable information from a `subType`.\n* `Type resolveGenericType(Class\u003c?\u003e type, Type subType)`\n\u003cbr\u003eResolves the generic `type` using type variable information from a `subType`.\n* `Class\u003c?\u003e resolveRawClass(Type genericType, Class\u003c?\u003e subType)`\n\u003cbr\u003eResolves the raw class for a `genericType` using type variable information from a `subType`. \n\n## Examples\n\nA typical use case is to [resolve arguments][resolve-raw-args] for a type, given a sub-type:\n\n```java\ninterface Foo\u003cT1, T2\u003e {}\nclass Bar implements Foo\u003cInteger, String\u003e {}\n\nClass\u003c?\u003e[] typeArgs = TypeResolver.resolveRawArguments(Foo.class, Bar.class);\n\nassert typeArgs[0] == Integer.class;\nassert typeArgs[1] == String.class;\n```\n\nType arguments can also be resolved from lambda expressions:\n\n```java\nFunction\u003cString, Integer\u003e strToInt = s -\u003e Integer.valueOf(s);\nClass\u003c?\u003e[] typeArgs = TypeResolver.resolveRawArguments(Function.class, strToInt.getClass());\n\nassert typeArgs[0] == String.class;\nassert typeArgs[1] == Integer.class;\n```\n\nAnd from method references:\n\n```java\nComparator\u003cString\u003e comparator = String::compareToIgnoreCase;\nClass\u003c?\u003e typeArg = TypeResolver.resolveRawArgument(Comparator.class, comparator.getClass());\n\nassert typeArg == String.class;\n```\n\nWe can [reify] more complex generic type parameters:\n\n```java\ninterface Foo\u003cT\u003e {}\nclass Bar implements Foo\u003cList\u003cInteger\u003e\u003e {}\n\nType typeArgs = TypeResolver.reify(Foo.class, Bar.class);\n\nParameterizedType paramType = (ParameterizedType) typeArgs;\nType[] actualTypeArgs = paramType.getActualTypeArguments();\nParameterizedType arg = (ParameterizedType)actualTypeArgs[0];\n\nassert paramType.getRawType() == Foo.class;\nassert arg1.getRawType() == List.class;\nassert arg1.getActualTypeArguments()[0] == Integer.class;\n```\n\nWe can also resolve the raw class for type parameters on fields and methods:\n\n```java\nclass Entity\u003cID extends Serializable\u003e {\n  ID id;\n  void setId(ID id) {}\n}\n\nclass SomeEntity extends Entity\u003cLong\u003e {}\n\nType fieldType = Entity.class.getDeclaredField(\"id\").getGenericType();\nType mutatorType = Entity.class.getDeclaredMethod(\"setId\", Serializable.class).getGenericParameterTypes()[0];\n\nassert TypeResolver.resolveRawClass(fieldType, SomeEntity.class) == Long.class;\nassert TypeResolver.resolveRawClass(mutatorType, SomeEntity.class) == Long.class;\n```\n\nAnd we can [reify generic type][reify-generic] parameters from fields or methods.\n\n## Common Use Cases\n\n[Layer supertypes](http://martinfowler.com/eaaCatalog/layerSupertype.html) often utilize type parameters that are populated by subclasses. A common use case for TypeTools is to resolve the type arguments for a layer supertype given a sub-type. \n\nFollowing is an example **Generic DAO** layer supertype implementation:\n\n```java\nclass Device {}\nclass Router extends Device {}\n\nclass GenericDAO\u003cT, ID extends Serializable\u003e {\n  protected Class\u003cT\u003e persistentClass;\n  protected Class\u003cID\u003e idClass;\n\n  private GenericDAO() {\n    Class\u003c?\u003e[] typeArguments = TypeResolver.resolveRawArguments(GenericDAO.class, getClass());\n    this.persistentClass = (Class\u003cT\u003e) typeArguments[0];\n    this.idClass = (Class\u003cID\u003e) typeArguments[1];\n  }\n}\n\nclass DeviceDAO\u003cT extends Device\u003e extends GenericDAO\u003cT, Long\u003e {}\nclass RouterDAO extends DeviceDAO\u003cRouter\u003e {}\n```\n\nWe can assert that type arguments are resolved as expected:\n\n```java\nRouterDAO routerDAO = new RouterDAO();\nassert routerDAO.persistentClass == Router.class;\nassert routerDAO.idClass == Long.class;\n```\n\n## Additional Features\n\nBy default, type variable information for each resolved type is weakly cached by the `TypeResolver`. Caching can be enabled/disabled via:\n\n```java\nTypeResolver.enableCache();\nTypeResolver.disableCache();\n```\n\n## Additional Notes\n\n#### On Lambda Support\n\nLambda type argument resolution is currently supported for:\n\n* Oracle JDK 8, 9\n* Open JDK 8, 9\n\n#### On Unresolvable Lambda Type Arguments\n\nWhen resolving type arguments with lambda expressions, only type parameters used in the functional interface's method signature can be resolved. Ex:\n\n```java\ninterface ExtraFunction\u003cT, R, Z\u003e extends Function\u003cT, R\u003e{}\nExtraFunction\u003cString, Integer, Long\u003e strToInt = s -\u003e Integer.valueOf(s);\nClass\u003c?\u003e[] typeArgs = TypeResolver.resolveRawArguments(Function.class, strToInt.getClass());\n\nassert typeArgs[0] == String.class;\nassert typeArgs[1] == Integer.class;\nassert typeArgs[2] == Unknown.class;\n```\n\nSince the type parameter `Z` in this example is unused by `Function`, its argument resolves to `Unknown.class`.\n\n#### On OSGi Support\n\nWhen using TypeTools in an OSGi environment where lambda or method reference type argument resolution is desired, the `sun.reflect` system package should be exported to the application bundles. For example, for Felix, add the following to your config.properties file:\n\n```\norg.osgi.framework.system.packages.extra=sun.reflect\n```\n\n## Docs\n\nJavaDocs are available [here](https://jodah.net/typetools/javadoc).\n\n## License\n\nCopyright Jonathan Halterman and friends. Released under the [Apache 2.0 license](http://www.apache.org/licenses/LICENSE-2.0.html).\n\n[resolve-raw-args]: http://jodah.net/typetools/javadoc/net/jodah/typetools/TypeResolver.html#resolveRawArguments-java.lang.Class-java.lang.Class-\n[reify]: http://jodah.net/typetools/javadoc/net/jodah/typetools/TypeResolver.html#reify-java.lang.Class-java.lang.Class-\n[reify-generic]: http://jodah.net/typetools/javadoc/net/jodah/typetools/TypeResolver.html#reify-java.lang.reflect.Type-\n","funding_links":[],"categories":["Projects","项目","Miscellaneous"],"sub_categories":["Miscellaneous","杂项"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjhalterman%2Ftypetools","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjhalterman%2Ftypetools","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjhalterman%2Ftypetools/lists"}