java反射獲取注解_Java自定義注解和運行時靠反射獲取注解

java自定義注解

Java注解是附加在代碼中的一些元信息,用于一些工具在編譯、運行時進行解析和使用,起到說明、配置的功能。

注解不會也不能影響代碼的實際邏輯,僅僅起到輔助性的作用。包含在 java.lang.annotation 包中。

1、元注解

元注解是指注解的注解。包括 @Retention @Target @Document @Inherited四種。

1.1、@Retention: 定義注解的保留策略

@Retention(RetentionPolicy.SOURCE) //注解僅存在于源碼中,在class字節碼文件中不包含

@Retention(RetentionPolicy.CLASS) // 默認的保留策略,注解會在class字節碼文件中存在,但運行時無法獲得,

@Retention(RetentionPolicy.RUNTIME) // 注解會在class字節碼文件中存在,在運行時可以通過反射獲取到

注解類:

@Retention(RetentionPolicy.RUNTIME) // 注解會在class字節碼文件中存在,在運行時可以通過反射獲取到

@Target({ElementType.FIELD,ElementType.METHOD})//定義注解的作用目標**作用范圍字段、枚舉的常量/方法

@Documented//說明該注解將被包含在javadoc中

public @interface FieldMeta {

/**

* 是否為序列號

* @return

*/

boolean id() default false;

/**

* 字段名稱

* @return

*/

String name() default "";

/**

* 是否可編輯

* @return

*/

boolean editable() default true;

/**

* 是否在列表中顯示

* @return

*/

boolean summary() default true;

/**

* 字段描述

* @return

*/

String description() default "";

/**

* 排序字段

* @return

*/

int order() default 0;

}

實體類:

public class Anno {

@FieldMeta(id=true,name="序列號",order=1)

private int id;

@FieldMeta(name="姓名",order=3)

private String name;

@FieldMeta(name="年齡",order=2)

private int age;

@FieldMeta(description="描述",order=4)

public String desc(){

return "java反射獲取annotation的測試";

}

public int getId() {

return id;

}

public void setId(int id) {

this.id = id;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public int getAge() {

return age;

}

public void setAge(int age) {

this.age = age;

}

}

獲取到注解的幫助類:

public class SortableField {

public SortableField(){}

public SortableField(FieldMeta meta, Field field) {

super();

this.meta = meta;

this.field = field;

this.name=field.getName();

this.type=field.getType();

}

public SortableField(FieldMeta meta, String name, Class> type) {

super();

this.meta = meta;

this.name = name;

this.type = type;

}

private FieldMeta meta;

private Field field;

private String name;

private Class> type;

public FieldMeta getMeta() {

return meta;

}

public void setMeta(FieldMeta meta) {

this.meta = meta;

}

public Field getField() {

return field;

}

public void setField(Field field) {

this.field = field;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public Class> getType() {

return type;

}

public void setType(Class> type) {

this.type = type;

}

}

運行時獲取注解,首先創建一個基類:

public class Parent {

private Class entity;

public Parent() {

init();

}

@SuppressWarnings("unchecked")

public List init(){

List list = new ArrayList();

/**getClass().getGenericSuperclass()返回表示此 Class 所表示的實體(類、接口、基本類型或 void)

* 的直接超類的 Type(Class泛型中的類型),然后將其轉換ParameterizedType。。

* getActualTypeArguments()返回表示此類型實際類型參數的 Type 對象的數組。

* [0]就是這個數組中第一個了。。

* 簡而言之就是獲得超類的泛型參數的實際類型。。*/

entity = (Class)((ParameterizedType)this.getClass().getGenericSuperclass())

.getActualTypeArguments()[0];

// FieldMeta filed = entity.getAnnotation(FieldMeta.class);

if(this.entity!=null){

/**返回類中所有字段,包括公共、保護、默認(包)訪問和私有字段,但不包括繼承的字段

* entity.getFields();只返回對象所表示的類或接口的所有可訪問公共字段

* 在class中getDeclared**()方法返回的都是所有訪問權限的字段、方法等;

* 可看API

* */

Field[] fields = entity.getDeclaredFields();

//

for(Field f : fields){

//獲取字段中包含fieldMeta的注解

FieldMeta meta = f.getAnnotation(FieldMeta.class);

if(meta!=null){

SortableField sf = new SortableField(meta, f);

list.add(sf);

}

}

//返回對象所表示的類或接口的所有可訪問公共方法

Method[] methods = entity.getMethods();

for(Method m:methods){

FieldMeta meta = m.getAnnotation(FieldMeta.class);

if(meta!=null){

SortableField sf = new SortableField(meta,m.getName(),m.getReturnType());

list.add(sf);

}

}

//這種方法是新建FieldSortCom類實現Comparator接口,來重寫compare方法實現排序

// Collections.sort(list, new FieldSortCom());

Collections.sort(list, new Comparator() {

@Override

public int compare(SortableField s1,SortableField s2) {

return s1.getMeta().order()-s2.getMeta().order();

// return s1.getName().compareTo(s2.getName());//也可以用compare來比較

}

});

}

return list;

}

}

創建子類繼承基類:

public class Child extends Parent{

}

測試類:

public class TestAnnotation {

@SuppressWarnings({ "unchecked", "rawtypes" })

public static void main(String[] args) {

Parent c = new Child();

List list = c.init();//獲取泛型中類里面的注解

//輸出結果

for(SortableField l : list){

System.out.println("字段名稱:"+l.getName()+"\t字段類型:"+l.getType()+

"\t注解名稱:"+l.getMeta().name()+"\t注解描述:"+l.getMeta().description());

}

}

}

轉:

1、Annotation的工作原理:

JDK5.0中提供了注解的功能,允許開發者定義和使用自己的注解類型。該功能由一個定義注解類型的語法和描述一個注解聲明的語法,讀取注解的API,一個使用注解修飾的class文件和一個注解處理工具組成。

Annotation并不直接影響代碼的語義,但是他可以被看做是程序的工具或者類庫。它會反過來對正在運行的程序語義有所影響。

Annotation可以沖源文件、class文件或者在運行時通過反射機制多種方式被讀取。

2、@Override注解:

java.lang

注釋類型 Override

@Target(value=METHOD)

@Retention(value=SOURCE)

public @interface Override

表示一個方法聲明打算重寫超類中的另一個方法聲明。如果方法利用此注釋類型進行注解但沒有重寫超類方法,則編譯器會生成一條錯誤消息。

@Override注解表示子類要重寫父類的對應方法。

Override是一個Marker annotation,用于標識的Annotation,Annotation名稱本身表示了要給工具程序的信息。

下面是一個使用@Override注解的例子:

class A {

private String id;

A(String id){

this.id = id;

}

@Override

public String toString() {

return id;

}

}

3、@Deprecated注解:

java.lang

注釋類型 Deprecated

@Documented

@Retention(value=RUNTIME)

public @interface Deprecated

用 @Deprecated 注釋的程序元素,不鼓勵程序員使用這樣的元素,通常是因為它很危險或存在更好的選擇。在使用不被贊成的程序元素或在不被贊成的代碼中執行重寫時,編譯器會發出警告。

@Deprecated注解表示方法是不被建議使用的。

Deprecated是一個Marker annotation。

下面是一個使用@Deprecated注解的例子:

class A {

private String id;

A(String id){

this.id = id;

}

@Deprecated

public void execute(){

System.out.println(id);

}

public static void main(String[] args) {

A a = new A("a123");

a.execute();

}

}

4、@SuppressWarnings注解:

java.lang

注釋類型 SuppressWarnings

@Target(value={TYPE,FIELD,METHOD,PARAMETER,CONSTRUCTOR,LOCAL_VARIABLE})

@Retention(value=SOURCE)

public @interface SuppressWarnings

指示應該在注釋元素(以及包含在該注釋元素中的所有程序元素)中取消顯示指定的編譯器警告。注意,在給定元素中取消顯示的警告集是所有包含元素中取消顯示的警告的超集。例如,如果注釋一個類來取消顯示某個警告,同時注釋一個方法來取消顯示另一個警告,那么將在此方法中同時取消顯示這兩個警告。

根據風格不同,程序員應該始終在最里層的嵌套元素上使用此注釋,在那里使用才有效。如果要在特定的方法中取消顯示某個警告,則應該注釋該方法而不是注釋它的類。

@SuppressWarnings注解表示抑制警告。

下面是一個使用@SuppressWarnings注解的例子:

@SuppressWarnings("unchecked")

public static void main(String[] args) {

List list = new ArrayList();

list.add("abc");

}

5、自定義注解:

使用@interface自定義注解時,自動繼承了java.lang.annotation.Annotation接口,由編譯程序自動完成其他細節。在定義注解時,不能繼承其他的注解或接口。

自定義最簡單的注解:

public @interface MyAnnotation {

}

使用自定義注解:

public class AnnotationTest2 {

@MyAnnotation

public void execute(){

System.out.println("method");

}

}

5.1、添加變量:

public @interface MyAnnotation {

String value1();

}

使用自定義注解:

public class AnnotationTest2 {

@MyAnnotation(value1="abc")

public void execute(){

System.out.println("method");

}

}

當注解中使用的屬性名為value時,對其賦值時可以不指定屬性的名稱而直接寫上屬性值接口;除了value意外的變量名都需要使用name=value的方式賦值。

5.2、添加默認值:

public @interface MyAnnotation {

String value1() default "abc";

}

5.3、多變量使用枚舉:

public @interface MyAnnotation {

String value1() default "abc";

MyEnum value2() default MyEnum.Sunny;

}

enum MyEnum{

Sunny,Rainy

}

使用自定義注解:

public class AnnotationTest2 {

@MyAnnotation(value1="a", value2=MyEnum.Sunny)

public void execute(){

System.out.println("method");

}

}

5.4、數組變量:

public @interface MyAnnotation {

String[] value1() default "abc";

}

使用自定義注解:

public class AnnotationTest2 {

@MyAnnotation(value1={"a","b"})

public void execute(){

System.out.println("method");

}

}

6、設置注解的作用范圍:

@Documented

@Retention(value=RUNTIME)

@Target(value=ANNOTATION_TYPE)

public @interface Retention

指示注釋類型的注釋要保留多久。如果注釋類型聲明中不存在 Retention 注釋,則保留策略默認為 RetentionPolicy.CLASS。

只有元注釋類型直接用于注釋時,Target 元注釋才有效。如果元注釋類型用作另一種注釋類型的成員,則無效。

public enum RetentionPolicy

extends Enum

注釋保留策略。此枚舉類型的常量描述保留注釋的不同策略。它們與 Retention 元注釋類型一起使用,以指定保留多長的注釋。

CLASS

編譯器將把注釋記錄在類文件中,但在運行時 VM 不需要保留注釋。

RUNTIME

編譯器將把注釋記錄在類文件中,在運行時 VM 將保留注釋,因此可以反射性地讀取。

SOURCE

編譯器要丟棄的注釋。

@Retention注解可以在定義注解時為編譯程序提供注解的保留策略。

屬于CLASS保留策略的注解有@SuppressWarnings,該注解信息不會存儲于.class文件。

6.1、在自定義注解中的使用例子:

@Retention(RetentionPolicy.CLASS)

public @interface MyAnnotation {

String[] value1() default "abc";

}

7、使用反射讀取RUNTIME保留策略的Annotation信息的例子:

java.lang.reflect

接口 AnnotatedElement

所有已知實現類:

AccessibleObject, Class, Constructor, Field, Method, Package

表示目前正在此 VM 中運行的程序的一個已注釋元素。該接口允許反射性地讀取注釋。由此接口中的方法返回的所有注釋都是不可變并且可序列化的。調用者可以修改已賦值數組枚舉成員的訪問器返回的數組;這不會對其他調用者返回的數組產生任何影響。

如果此接口中的方法返回的注釋(直接或間接地)包含一個已賦值的 Class 成員,該成員引用了一個在此 VM 中不可訪問的類,則試圖通過在返回的注釋上調用相關的類返回的方法來讀取該類,將導致一個 TypeNotPresentException。

isAnnotationPresent

boolean isAnnotationPresent(Class extends Annotation> annotationClass)

如果指定類型的注釋存在于此元素上,則返回 true,否則返回 false。此方法主要是為了便于訪問標記注釋而設計的。

參數:

annotationClass - 對應于注釋類型的 Class 對象

返回:

如果指定注釋類型的注釋存在于此對象上,則返回 true,否則返回 false

拋出:

NullPointerException - 如果給定的注釋類為 null

從以下版本開始:

1.5

getAnnotation

T getAnnotation(Class annotationClass)

如果存在該元素的指定類型的注釋,則返回這些注釋,否則返回 null。

參數:

annotationClass - 對應于注釋類型的 Class 對象

返回:

如果該元素的指定注釋類型的注釋存在于此對象上,則返回這些注釋,否則返回 null

拋出:

NullPointerException - 如果給定的注釋類為 null

從以下版本開始:

1.5

getAnnotations

Annotation[] getAnnotations()

返回此元素上存在的所有注釋。(如果此元素沒有注釋,則返回長度為零的數組。)該方法的調用者可以隨意修改返回的數組;這不會對其他調用者返回的數組產生任何影響。

返回:

此元素上存在的所有注釋

從以下版本開始:

1.5

getDeclaredAnnotations

Annotation[] getDeclaredAnnotations()

返回直接存在于此元素上的所有注釋。與此接口中的其他方法不同,該方法將忽略繼承的注釋。(如果沒有注釋直接存在于此元素上,則返回長度為零的一個數組。)該方法的調用者可以隨意修改返回的數組;這不會對其他調用者返回的數組產生任何影響。

返回:

直接存在于此元素上的所有注釋

從以下版本開始:

1.5

下面是使用反射讀取RUNTIME保留策略的Annotation信息的例子:

自定義注解:

@Retention(RetentionPolicy.RUNTIME)

public @interface MyAnnotation {

String[] value1() default "abc";

}

使用自定義注解:

public class AnnotationTest2 {

@MyAnnotation(value1={"a","b"})

@Deprecated

public void execute(){

System.out.println("method");

}

}

讀取注解中的信息:

public static void main(String[] args) throws SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException {

AnnotationTest2 annotationTest2 = new AnnotationTest2();

//獲取AnnotationTest2的Class實例

Class c = AnnotationTest2.class;

//獲取需要處理的方法Method實例

Method method = c.getMethod("execute", new Class[]{});

//判斷該方法是否包含MyAnnotation注解

if(method.isAnnotationPresent(MyAnnotation.class)){

//獲取該方法的MyAnnotation注解實例

MyAnnotation myAnnotation = method.getAnnotation(MyAnnotation.class);

//執行該方法

method.invoke(annotationTest2, new Object[]{});

//獲取myAnnotation

String[] value1 = myAnnotation.value1();

System.out.println(value1[0]);

}

//獲取方法上的所有注解

Annotation[] annotations = method.getAnnotations();

for(Annotation annotation : annotations){

System.out.println(annotation);

}

}

8、限定注解的使用:

限定注解使用@Target。

@Documented

@Retention(value=RUNTIME)

@Target(value=ANNOTATION_TYPE)

public @interface Target

指示注釋類型所適用的程序元素的種類。如果注釋類型聲明中不存在 Target 元注釋,則聲明的類型可以用在任一程序元素上。如果存在這樣的元注釋,則編譯器強制實施指定的使用限制。 例如,此元注釋指示該聲明類型是其自身,即元注釋類型。它只能用在注釋類型聲明上:

@Target(ElementType.ANNOTATION_TYPE)

public @interface MetaAnnotationType {

...

}

此元注釋指示該聲明類型只可作為復雜注釋類型聲明中的成員類型使用。它不能直接用于注釋:

@Target({})

public @interface MemberType {

...

}

這是一個編譯時錯誤,它表明一個 ElementType 常量在 Target 注釋中出現了不只一次。例如,以下元注釋是非法的:

@Target({ElementType.FIELD, ElementType.METHOD, ElementType.FIELD})

public @interface Bogus {

...

}

public enum ElementType

extends Enum

程序元素類型。此枚舉類型的常量提供了 Java 程序中聲明的元素的簡單分類。

這些常量與 Target 元注釋類型一起使用,以指定在什么情況下使用注釋類型是合法的。

ANNOTATION_TYPE

注釋類型聲明

CONSTRUCTOR

構造方法聲明

FIELD

字段聲明(包括枚舉常量)

LOCAL_VARIABLE

局部變量聲明

METHOD

方法聲明

PACKAGE

包聲明

PARAMETER

參數聲明

TYPE

類、接口(包括注釋類型)或枚舉聲明

注解的使用限定的例子:

@Target(ElementType.METHOD)

public @interface MyAnnotation {

String[] value1() default "abc";

}

9、在幫助文檔中加入注解:

要想在制作JavaDoc文件的同時將注解信息加入到API文件中,可以使用java.lang.annotation.Documented。

在自定義注解中聲明構建注解文檔:

@Documented

public @interface MyAnnotation {

String[] value1() default "abc";

}

使用自定義注解:

public class AnnotationTest2 {

@MyAnnotation(value1={"a","b"})

public void execute(){

System.out.println("method");

}

}

10、在注解中使用繼承:

默認情況下注解并不會被繼承到子類中,可以在自定義注解時加上java.lang.annotation.Inherited注解聲明使用繼承。

@Documented

@Retention(value=RUNTIME)

@Target(value=ANNOTATION_TYPE)

public @interface Inherited

指示注釋類型被自動繼承。如果在注釋類型聲明中存在 Inherited 元注釋,并且用戶在某一類聲明中查詢該注釋類型,同時該類聲明中沒有此類型的注釋,則將在該類的超類中自動查詢該注釋類型。此過程會重復進行,直到找到此類型的注釋或到達了該類層次結構的頂層 (Object) 為止。如果沒有超類具有該類型的注釋,則查詢將指示當前類沒有這樣的注釋。

注意,如果使用注釋類型注釋類以外的任何事物,此元注釋類型都是無效的。還要注意,此元注釋僅促成從超類繼承注釋;對已實現接口的注釋無效。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/395824.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/395824.shtml
英文地址,請注明出處:http://en.pswp.cn/news/395824.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

進程間的通訊(IPC)方式

內存映射 為什么要進行進程間的通訊(IPC (Inter-process communication)) 數據傳輸:一個進程需要將它的數據發送給另一個進程,發送的數據量在一個字節到幾M字節之間共享數據:多個進程想要操作共享數據,一個進程對共享數據的修改&a…

開發人員避免編寫測試的2個最常見原因

This post was originally published on Medium這篇文章最初發表于Medium Writing tests represents one of those few stages of software development that is usually overlooked, even though it may be one of the most important one. Developers mention it and usuall…

java ews_Java---使用EWS 寫個ExchangeMailUtil

依賴包:commons-httpclient-3.1.jarcommons-codec-1.10.jarcommons-logging-1.2.jarjcifs-1.3.17.jar代碼示例:創建MailBean類:import java.util.Date;public class MailBean {public BigDecimal getId() {return id;}public void setId(BigD…

Ilya Muromets(DP or 思維)

Ilya Muromets Gym - 100513F Силачом слыву недаром — семерых одним ударом!From the Russian cartoon on the German fairy tale.Ilya Muromets is a legendary bogatyr. Right now he is struggling against Zmej Gorynych, a drago…

C# 裝箱和拆箱

C#的值類型可以分為在棧上分配內存的值類型和在托管堆上分配內存的引用類型。 1、那么值類型和引用類型能否相互轉換呢? 答案是肯定的,C#通過裝箱和拆箱來實現兩者的相互轉換。 (1)、裝箱 ---把值類型強制轉換成引用類型(object類型) (2)、拆箱 ---把引用類型強制轉換成值…

第五章

學會了開發板測試環境的調試和燒寫android系統。 學到的知識: 一、安裝串口調試工具:minicom 第1步:檢測當前系統是否支持USB轉串口。 # lsmod | grep usbserial 第2步:安裝minicom # qpt-get install minicom 第3步:配置minicom # minicom -…

Angular的后院:組件依賴關系的解決

by Dor Moshe通過Dor Moshe Angular的后院:解決 組件依賴關系 (Angular’s Backyard: The Resolving of Components Dependencies) This article originally appeared on dormoshe.io這篇文章 最初出現在dormoshe.io Many of us use the Hierarchical Dependenc…

node中的Stream-Readable和Writeable解讀

在node中,只要涉及到文件IO的場景一般都會涉及到一個類-Stream。Stream是對IO設備的抽象表示,其在JAVA中也有涉及,主要體現在四個類-InputStream、Reader、OutputStream、Writer,其中InputStream和OutputSt…

新Rider預覽版發布,對F#的支持是亮點

JetBrains一直在改進自己的跨平臺.NET IDE產品Rider,努力使其成為Visual Studio家族產品可承擔職能的重要替代者。于今年四月發布的Rider預覽版(EAP 21)提供了一些新特性,其中的亮點在于對函數式編程語言F#的支持。\\鑒于這是Ride…

java代碼整合_java合并多個文件的實例代碼

在實際項目中,在處理較大的文件時,常常將文件拆分為多個子文件進行處理,最后再合并這些子文件。下面就為各位介紹下Java中合并多個文件的方法。Java中合并子文件最容易想到的就是利用BufferedStream進行讀寫。具體的實現方式如下,…

正則表達式的一些規則

1.限定修飾符只對其緊前的元字符有效 String rex8 "\\d\\D"; 上式中,只對\\D有效,即有至少有1個(1個或多個)非數字,\\d仍然只許有一個數字。 2.[1,2,3]和[123]是一樣的轉載于:https://www.cnblogs.com/Sabr…

2016版單詞的減法_在2016年最大的電影中,女性只說了27%的單詞。

2016版單詞的減法by Amber Thomas通過琥珀托馬斯 在2016年最大的電影中,女性只說了27%的單詞。 (Women only said 27% of the words in 2016’s biggest movies.) Movie trailers in 2016 promised viewers so many strong female characters. Jyn Erso…

軟件工程博客---團隊項目---個人設計2(算法)

針對分析我們團隊項目的需求,我們選定Dijkstra算法。 算法的基本思想: Dijkstra算法是由E.W.Dijkstra于1959年提出,又叫迪杰斯特拉算法,它應用了貪心算法模式,是目前公認的最好的求解最短路徑的方法。算法解決的是有向…

UWP 雜記

UWP用選取文件對話框 http://blog.csdn.net/u011033906/article/details/65448394 文件選取器、獲取文件屬性、寫入和讀取、保存讀取和刪除應用數據 https://yq.aliyun.com/articles/839 UWP判斷文件是否存在 http://blog.csdn.net/lindexi_gd/article/details/51387901…

微信上傳素材 java_微信素材上傳(JAVA)

public String uploadMaterial(String url,InputStream sbs,String filelength,String filename, String type) throws Exception {try {DataInputStream innew DataInputStream(sbs);url url.replace("TYPE", type);URL urlObj new URL(url);// 創建Http連接HttpU…

SQL Server讀寫分離之發布訂閱

一、發布 上面有多種發布方式,這里我選擇事物發布,具體區別請自行百度。 點擊下一步、然后繼續選擇需要發布的對象。 如果需要篩選發布的數據點擊添加。 根據自己的計劃選擇發布的時間。 點擊安全設置,設置代理信息。 最后單擊完成系統會自動…

碼農和程序員的幾個重要區別!

如果一個企業老板大聲嚷嚷說,“我要招個程序員”,那么十之八九指的是“碼農”——一種純粹為了錢而寫代碼的技術人員。這其實是一種非常狹隘和錯誤的做法,原因么,且聽我一一道來。1、碼農寫代碼,程序員寫系統從本質上講…

sql server2008禁用遠程連接

1.打開SQL Server 配置管理器,雙擊左邊 SQL Server 網絡配置,點擊TCP/IP協議,在協議一欄中,找到 全部偵聽,修改為否,然后點擊IP地址,將IP地址為127.0.0.1(IPV4)或::1(IPV6)的已啟用修改為是,其它的IP地址的已啟用修改為否 注意:如…

snapchat注冊不到_從Snapchat獲得開發人員職位中學到的經驗教訓

snapchat注冊不到Here are three links worth your time:這是三個值得您花費時間的鏈接: I just got a developer job at Snapchat. Here’s what I learned and how it can help you with your job search (15 minute read) 我剛剛在Snapchat獲得開發人員職位。 這…

java bitmap jar_Java面試中常用的BitMap代碼

引言阿里內推面試的時候被考了一道編程題:10億個范圍為1~2048的整數,將其去重并計算數字數目。我看到這個題目就想起來了《編程珠璣》第一章講的叫做BitMap的數據結構,但是我并沒有在java上實現過,這就比較尷尬了,再加…