亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

java注解處理器學(xué)習(xí)在編譯期修改語(yǔ)法樹教程

 更新時(shí)間:2022年09月20日 10:02:33   作者:煩啦  
這篇文章主要為大家介紹了java注解處理器學(xué)習(xí)在編譯期修改語(yǔ)法樹教程,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

從需求說起

由于相關(guān)政策,最近公司安全部要求各系統(tǒng)在rpc接口調(diào)用的交互過程中把相應(yīng)的參數(shù)及結(jié)果以相應(yīng)的格式發(fā)送到安全部統(tǒng)一記錄,例如參數(shù)或結(jié)果含手機(jī)號(hào)和郵箱則格式如:“mail:axxx@126.com,phone:183xxxx1967”,其它系統(tǒng)信息等先忽略。

以便在數(shù)據(jù)泄露時(shí)可據(jù)此分析出數(shù)據(jù)的泄露源頭,以及若有黑客攻克有些接口時(shí)公司能有跡可循。

總體架構(gòu)是各個(gè)接口把入?yún)⒑徒Y(jié)果打印日志,然后由統(tǒng)一的日志收集器收集日志通過mq發(fā)送到安全部。這樣每個(gè)系統(tǒng)只用在接口中添加參數(shù)和結(jié)果的打日志代碼。

添加打印日志代碼的方案

第一種方案,硬編碼

即直接在接口中編寫打印日志的代碼。這種工作量太大,公司各個(gè)部門,以往積累了眾多的項(xiàng)目,這樣改造的工作量太大。

第二種方案,AOP

利用aop框架,在切面類中打印日志??梢允褂胹pring 支持的aop功能或其他aop框架。

這個(gè)方案應(yīng)該來說改動(dòng)及工作量都大大降低,公司也是采用的這種方案。但是其弊端也很明顯,

一、是對(duì)框架的依賴(如用spring aop的話則非spring項(xiàng)目則不適用)

二、就是不同的項(xiàng)目或接口,入?yún)⒒蚪Y(jié)果變量名不同,如手機(jī)號(hào):有的叫mobilePhone, 有的叫telephone等;但打印日志時(shí)要統(tǒng)一打印,如:phone:183xxxx1967; 所以要在參數(shù)上加注解,以表明打印日志時(shí)的名稱。這個(gè)重復(fù)工作量也不小。

第三種方案,修改class文件

針對(duì)第二種方案的弊端,我設(shè)計(jì)出這第三種方案。

利用相關(guān)技術(shù),直接修改class文件,在接口中添加打印日志的字節(jié)碼。例如Javassist,asm等技術(shù)。

通過調(diào)研,在編譯期通過修改語(yǔ)法樹來達(dá)到修改class文件的效果,這種對(duì)用戶來說完全透明,不依賴任何框架。針對(duì)弊端二則發(fā)明名稱分析模塊,讓程序自動(dòng)分析出參數(shù)的含義,從而避免了手工添加注解的麻煩。

下面就具體說明第三種方案的實(shí)現(xiàn):

利用JDK的注解處理器,可在編譯期間對(duì)注解處理,可以讀取、修改、添加抽象語(yǔ)法樹中的任意元素。

注解處理器是JDK1.6開始提供的功能,利用注解處理器可以干涉編譯器的行為,只要有足夠的創(chuàng)意,可以利用注解處理器實(shí)現(xiàn)許多原本只能在編碼中完成的事情。

注解處理器的用法:

1、實(shí)現(xiàn)AbstractProcessor

實(shí)現(xiàn)init和process方法

顧名思義,init是完成一些初始化工作;process完成具體的邏輯處理。后邊會(huì)有具體的例子說明。

2、添加注解

@SupportedAnnotationTypes 指定此注解處理器支持的注解,可用*指定所有注解

@SupportedSourceVersion 指定支持的java的版本

注解實(shí)例:

在process方法中可獲取到注解有@Safety的類和方法。

Set<? extends Element> set = roundEnv.getElementsAnnotatedWith(Safety.class);

然后可遍歷方法,獲取到方法的入?yún)?,分析入?yún)?,給方法的語(yǔ)法樹添加打印參數(shù)日志的代碼。對(duì)于方法的結(jié)果是同樣的道理。

關(guān)于對(duì)語(yǔ)法樹的操作,網(wǎng)上資料相對(duì)較少及較為片段,介紹起來篇幅略長(zhǎng),故放在最后面進(jìn)行介紹。

名稱分析模塊的思想及設(shè)計(jì)

剩下的一個(gè)關(guān)鍵問題是如何把不同的參數(shù)名統(tǒng)一成打印日志時(shí)的名稱,例如參數(shù)名為mobilePhone或telephone,但要打印的是phone。如果在注解屬性中指定的話,通過注解可以獲取到,但是當(dāng)接口或參數(shù)很多的情況下也是一件重復(fù)性的力氣活。

故我設(shè)計(jì)出一種不讓開發(fā)人員手動(dòng)指定名稱的方案,既對(duì)老的項(xiàng)目修改的少,又減輕開發(fā)人員的工作量,對(duì)新項(xiàng)目的應(yīng)用也是高效率的。

如圖:

詞庫(kù)存儲(chǔ)(可用類的靜態(tài)字段存儲(chǔ))需要打印的日志名稱及其對(duì)應(yīng)的詞根及單詞。如:

上圖紅框?yàn)榇蛴∪罩緯r(shí)要打印的名稱。綠框中為詞根及單詞:如若業(yè)務(wù)參數(shù)有用postbox作為郵箱變量名的則也可把postbox加入到mail的詞庫(kù)中。

這樣當(dāng)業(yè)務(wù)參數(shù)為mobilePhone或telephone時(shí),名稱分析模塊能夠分析出參數(shù)名包含phone詞根,從而得到對(duì)應(yīng)的打印日志名“phone”;這就要求業(yè)務(wù)參數(shù)的名義要有具體的含義,不能隨便字母組合沒有含義的詞語(yǔ),這應(yīng)該也是每個(gè)公司開發(fā)時(shí)的基本要求。

這里只是舉例一個(gè)簡(jiǎn)單的可行性方案,名稱分析模塊也可利用AI技術(shù),根據(jù)輸入的變量名利用智能技術(shù)分析出此變量名的含義。

語(yǔ)法樹的操作:

下面對(duì)語(yǔ)法樹的操作進(jìn)行詳細(xì)的說明,這里需要提到三個(gè)類:

JavacTrees 提供了待處理的抽象語(yǔ)法樹TreeMaker 封裝了創(chuàng)建AST節(jié)點(diǎn)的一些方法Names 提供了創(chuàng)建標(biāo)識(shí)符的方法

可在init方法中對(duì)這三個(gè)類初始化,以便在process方法中利用它們對(duì)語(yǔ)法樹進(jìn)行操作。如圖:

AST(抽象語(yǔ)法樹)是一種用來描述程序代碼語(yǔ)法結(jié)構(gòu)的樹形表示方式,語(yǔ)法樹的每一個(gè)節(jié)點(diǎn)都代表著程序代碼中的一個(gè)語(yǔ)法結(jié)構(gòu),例如包、類型、修飾符、運(yùn)算符、接口、返回值,甚至代碼注釋等都可以是一個(gè)語(yǔ)法結(jié)構(gòu)。

JCTree的介紹

JCTree

JCTree是語(yǔ)法樹元素的基類。

如上圖,它包含兩個(gè)屬性,

字段type表示語(yǔ)法結(jié)構(gòu)的類型

字段pos用于指明當(dāng)前語(yǔ)法樹節(jié)點(diǎn)(JCTree)在語(yǔ)法樹中的位置,因此我們不能直接用new關(guān)鍵字來創(chuàng)建語(yǔ)法樹節(jié)點(diǎn),即使創(chuàng)建了也沒有意義,而要用TreeMaker來進(jìn)行操作。

重點(diǎn)介紹幾個(gè)JCTree的子類:

JCStatement:聲明語(yǔ)法樹節(jié)點(diǎn),常見的子類如下 JCBlock:語(yǔ)句塊JCReturn:return語(yǔ)句JCClassDecl:類定義JCVariableDecl:字段/變量定義JCIf: if語(yǔ)句

   2.JCMethodDecl:方法定義語(yǔ)法樹節(jié)點(diǎn)

   3.JCModifiers:訪問標(biāo)志語(yǔ)法樹節(jié)點(diǎn)

   4.JCExpression:表達(dá)式語(yǔ)法樹節(jié)點(diǎn),常見的子類如下

JCAssign:賦值語(yǔ)句JCAssignOp:+=JCIdent:標(biāo)識(shí)符,可以是變量,類型,關(guān)鍵字等等JCLiteral: 字面量表達(dá)式,如123, “string”等JCBinary:二元操作符

JCTree的子類很多,大部分可以從字面上看出其意義

如上圖,在jdk1.8.0_65里JCTree有58個(gè)子類。

下面具體介紹對(duì)語(yǔ)法樹的操作。

TreeMaker

TreeMaker創(chuàng)建語(yǔ)法樹節(jié)點(diǎn)的所有方法,創(chuàng)建時(shí)會(huì)為創(chuàng)建出來的JCTree設(shè)置pos字段,所以必須用上下文相關(guān)的TreeMaker對(duì)象來創(chuàng)建語(yǔ)法樹節(jié)點(diǎn),而不能直接new語(yǔ)法樹節(jié)點(diǎn)。

TreeMaker.Modifiers

該方法用于創(chuàng)建訪問標(biāo)志語(yǔ)法樹節(jié)點(diǎn)(JCModifiers),源碼如下:

public JCModifiers Modifiers(long flags, List<JCAnnotation> annotations) {
        JCModifiers tree = new JCModifiers(flags, annotations);
        boolean noFlags = (flags & Flags.StandardFlags) == 0;
        tree.pos = (noFlags && annotations.isEmpty()) ? Position.NOPOS : pos;
        return tree;
    }
    public JCModifiers Modifiers(long flags) {
        return Modifiers(flags, List.<JCAnnotation>nil());
    }

參數(shù)解釋:

flags:訪問標(biāo)志

annotations:注解列表

其中flags可以用枚舉類型com.sun.tools.javac.code.Flags,且支持相加(Flags的值按二進(jìn)制設(shè)計(jì)),如圖:

用法示例:treeMaker.Modifiers(Flags.PUBLIC + Flags.STATIC + Flags.FINAL);

TreeMaker.ClassDef

該方法用于創(chuàng)建類定義語(yǔ)法樹節(jié)點(diǎn)(JCClassDef),源碼如下:

public JCClassDecl ClassDef(JCModifiers mods,
                                Name name,
                                List<JCTypeParameter> typarams,
                                JCTree extending,
                                List<JCExpression> implementing,
                                List<JCTree> defs)
    {
        JCClassDecl tree = new JCClassDecl(mods,
                                     name,
                                     typarams,
                                     extending,
                                     implementing,
                                     defs,
                                     null);
        tree.pos = pos;
        return tree;
    }

參數(shù)解釋:

mods:訪問標(biāo)志

name:方法名

restype:返回類型

typarams:泛型參數(shù)列表

params:參數(shù)列表

thrown:異常聲明列表

body:方法體

defaultValue:默認(rèn)方法(可能是interface中的那個(gè)default)

m:方法符號(hào)

mtype:方法類型。包含多種類型,泛型參數(shù)類型、方法參數(shù)類型,異常參數(shù)類型、返回參數(shù)類型

TreeMaker.MethodDef

用于創(chuàng)建方法定義語(yǔ)法樹節(jié)點(diǎn)(JCMethodDecl),源碼如下:

public JCMethodDecl MethodDef(JCModifiers mods,
                               Name name,
                               JCExpression restype,
                               List<JCTypeParameter> typarams,
                               List<JCVariableDecl> params,
                               List<JCExpression> thrown,
                               JCBlock body,
                               JCExpression defaultValue)
    {
        JCMethodDecl tree = new JCMethodDecl(mods,
                                       name,
                                       restype,
                                       typarams,
                                       params,
                                       thrown,
                                       body,
                                       defaultValue,
                                       null);
        tree.pos = pos;
        return tree;
    }

參數(shù)解釋:

mods:訪問標(biāo)志

name:方法名

restype:返回類型

typarams:泛型參數(shù)列表

params:參數(shù)列表

thrown:異常聲明列表

body:方法體

defaultValue:默認(rèn)方法(可能是interface中的那個(gè)default)

m:方法符號(hào)

mtype:方法類型。包含多種類型,泛型參數(shù)類型、方法參數(shù)類型,異常參數(shù)類型、返回參數(shù)類型

TreeMaker.VarDef

用于創(chuàng)建字段/變量定義語(yǔ)法樹節(jié)點(diǎn)(JCVariableDecl),源碼如下:

public JCVariableDecl VarDef(JCModifiers mods, Name name, JCExpression vartype, JCExpression init) {
        JCVariableDecl tree = new JCVariableDecl(mods, name, vartype, init, null);
        tree.pos = pos;
        return tree;
    }

參數(shù)解釋:

mods:訪問標(biāo)志

vartype:類型

init:初始化語(yǔ)句

v:變量符號(hào)

TreeMaker.Ident

用于創(chuàng)建標(biāo)識(shí)符語(yǔ)法樹節(jié)點(diǎn)(JCIdent),源碼如下:

public JCIdent Ident(Name name) {
        JCIdent tree = new JCIdent(name, null);
        tree.pos = pos;
        return tree;
}
public JCIdent Ident(Symbol sym) {
        return (JCIdent)new JCIdent((sym.name != names.empty)
                                ? sym.name
                                : sym.flatName(), sym)
            .setPos(pos)
            .setType(sym.type);
}
public JCExpression Ident(JCVariableDecl param) {
        return Ident(param.sym);
}

TreeMaker.Return

用于創(chuàng)建return語(yǔ)句語(yǔ)法樹節(jié)點(diǎn)(JCReturn)

TreeMaker.NewClass

用于創(chuàng)建new語(yǔ)句語(yǔ)法樹節(jié)點(diǎn)(JCNewClass),源碼如下:

public JCNewClass NewClass(JCExpression encl,
                             List<JCExpression> typeargs,
                             JCExpression clazz,
                             List<JCExpression> args,
                             JCClassDecl def)
    {
        JCNewClass tree = new JCNewClass(encl, typeargs, clazz, args, def);
        tree.pos = pos;
        return tree;
    }

參數(shù)解釋:

encl:不太明白此參數(shù)含義

typeargs:參數(shù)類型列表

clazz:待創(chuàng)建對(duì)象的類型

args:參數(shù)列表

def:類定義

TreeMaker.Select

用于創(chuàng)建域訪問/方法訪問(當(dāng)是方法訪問時(shí),常和方法的調(diào)用TreeMaker.Apply一起使用語(yǔ)法樹節(jié)點(diǎn)(JCFieldAccess)

public JCFieldAccess Select(JCExpression selected,
    Name selector) 
{
        JCFieldAccess tree = new JCFieldAccess(selected, selector, null);
        tree.pos = pos;
        return tree;
}
public JCExpression Select(JCExpression base,
    Symbol sym) {
        return new JCFieldAccess(base, sym.name, sym).setPos(pos).setType(sym.type);
}

參數(shù)解釋:

selected:.運(yùn)算符左邊的表達(dá)式

selector:.運(yùn)算符右邊的名字

TreeMaker.Apply

用于創(chuàng)建方法調(diào)用語(yǔ)法樹節(jié)點(diǎn)(JCMethodInvocation),源碼如下:

public JCMethodInvocation Apply(List<JCExpression> typeargs,
                       JCExpression fn,
                       List<JCExpression> args)
    {
        JCMethodInvocation tree = new JCMethodInvocation(typeargs, fn, args);
        tree.pos = pos;
        return tree;
    }

參數(shù)解釋:

typeargs:參數(shù)類型列表

fn:調(diào)用語(yǔ)句

args:參數(shù)列表

TreeMaker.Assign

用于創(chuàng)建賦值語(yǔ)句語(yǔ)法樹節(jié)點(diǎn)(JCAssign),源碼如下:

public JCAssign Assign(JCExpression lhs, JCExpression rhs) {
        JCAssign tree = new JCAssign(lhs, rhs);
        tree.pos = pos;
        return tree;
    }

參數(shù)解釋:

lhs:賦值語(yǔ)句左邊表達(dá)式

rhs:賦值語(yǔ)句右邊表達(dá)式

TreeMaker.Exec

用于創(chuàng)建可執(zhí)行語(yǔ)句語(yǔ)法樹節(jié)點(diǎn)(JCExpressionStatement),源碼如下:

public JCExpressionStatement Exec(JCExpression expr) {
        JCExpressionStatement tree = new JCExpressionStatement(expr);
        tree.pos = pos;
        return tree;
    }

TreeMaker.Block

用于創(chuàng)建組合語(yǔ)句語(yǔ)法樹節(jié)點(diǎn)(JCBlock),源碼如下:

public JCBlock Block(long flags, List<JCStatement> stats) {
        JCBlock tree = new JCBlock(flags, stats);
        tree.pos = pos;
        return tree;
    }

參數(shù)解釋:

flags:訪問標(biāo)志

stats:語(yǔ)句列表

用法實(shí)例:

下面來介紹一下實(shí)例來加深對(duì)API用法的理解:

1、根據(jù)字符串獲取Name,(利用Names的fromString靜態(tài)方法)

private Name getNameFromString(String s) { return names.fromString(s); }

2、創(chuàng)建變量語(yǔ)句

private JCTree.JCVariableDecl makeVarDef(JCTree.JCModifiers modifiers, String name, JCTree.JCExpression vartype, JCTree.JCExpression init) {
        return treeMaker.VarDef(
                modifiers,
                getNameFromString(name), //名字
                vartype, //類型
                init //初始化語(yǔ)句
        );
    }

3、創(chuàng)建 域/方法 的多級(jí)訪問, 方法的標(biāo)識(shí)只能是最后一個(gè)

例如: java.lang.System.out.println

private JCTree.JCExpression memberAccess(String components) {
    String[] componentArray = components.split("\\.");
    JCTree.JCExpression expr = treeMaker.Ident(getNameFromString(componentArray[0]));
    for (int i = 1; i < componentArray.length; i++) {
        expr = treeMaker.Select(expr, getNameFromString(componentArray[i]));
    }
    return expr;
}

4、聲明變量并賦值(利用以上包裝的方法)

JCTree.JCVariableDecl var = makeVarDef(treeMaker.Modifiers(0), "xiao", memberAccess("java.lang.String"), treeMaker.Literal("methodName"));

生成語(yǔ)句為:String xiao = "methodName";

5、給變量賦值

private JCTree.JCExpressionStatement makeAssignment(JCTree.JCExpression lhs, JCTree.JCExpression rhs) {
    return treeMaker.Exec(
            treeMaker.Assign(
                    lhs,
                    rhs
            )
    );
}
makeAssignment(treeMaker.Ident(getNameFromString("xiao")), treeMaker.Literal("assignment test"));

生成的賦值語(yǔ)句為:xiao = "assignment test";

6、兩個(gè)字符串字面量相加并賦值

treeMaker.Exec(
                treeMaker.Assign(treeMaker.Ident(getNameFromString("xiao")),
                        treeMaker.Binary(
                                JCTree.Tag.PLUS,
                                treeMaker.Literal("-Binary operator one"),
                                treeMaker.Literal("-Binary operator two")
                        ))
        );

生成語(yǔ)句為:xiao = "-Binary operator one" + "-Binary operator two";

編譯器會(huì)對(duì)此語(yǔ)句進(jìn)行優(yōu)化,因?yàn)閮蓚€(gè)字面量在編譯器即能確定,所以編譯器會(huì)把此語(yǔ)句優(yōu)化為:“xiao = "-Binary operator one-Binary operator two";”

7、+=語(yǔ)句

treeMaker.Exec(
                treeMaker.Assignop(
                        JCTree.Tag.PLUS_ASG,
                        treeMaker.Ident(getNameFromString("xiao")),
                        treeMaker.Literal("-Assignop test")
                )
        );

生成語(yǔ)句為:xiao += "-Assignop test";

8、聲明整型變量并賦值

makeVarDef(treeMaker.Modifiers(0), "zhen", memberAccess("java.lang.Integer"), treeMaker.Literal(1));

生成語(yǔ)句為:Integer zhen = 1;

9、++語(yǔ)句

treeMaker.Exec(
                treeMaker.Unary(
                        JCTree.Tag.PREINC,
                        treeMaker.Ident(getNameFromString("zhen"))
                )
        );

生成語(yǔ)句:zhen++;

10、加法語(yǔ)句

treeMaker.Exec(
                treeMaker.Unary(
                        JCTree.Tag.PREINC,
                        treeMaker.Ident(getNameFromString("zhen"))
                )
        );

生成語(yǔ)句:zhen = zhen + 10;

11、方法調(diào)用(以輸出語(yǔ)句舉例)

treeMaker.Exec(
                treeMaker.Assign(
                        treeMaker.Ident(getNameFromString("zhen")),
                        treeMaker.Binary(
                                JCTree.Tag.PLUS,
                                treeMaker.Ident(getNameFromString("zhen")),
                                treeMaker.Literal(10)
                        ))
        );

生成語(yǔ)句:System.out.println(xiao);

12、方法調(diào)用,輸出字符串

JCTree.JCExpressionStatement printVar = treeMaker.Exec(treeMaker.Apply(
                List.of(memberAccess("java.lang.String")),//參數(shù)類型
                memberAccess("java.lang.System.out.println"),
                List.of(treeMaker.Ident(getNameFromString("xiao")))
                )
        );

生成語(yǔ)句:System.out.println("xiao test zhen");

13、if語(yǔ)句

treeMaker.If(
                treeMaker.Binary(
                        JCTree.Tag.LT,
                        treeMaker.Ident(getNameFromString("zhen")),
                        treeMaker.Literal(10)
                ),
                printVar,
                printLiteral
        );

生成語(yǔ)句:

if (zhen < 10) {

           System.out.println(xiao);

} else {

           System.out.println("xiao test zhen");

}

14、if語(yǔ)句(null判斷)

treeMaker.If(
                treeMaker.Parens(
                        treeMaker.Binary(
                                JCTree.Tag.NE,
                                treeMaker.Ident(getNameFromString("xiao")),
                                treeMaker.Literal(TypeTag.BOT, null))
                ),
                printVar,
                printLiteral
        )

生成語(yǔ)句:

if (xiao != null) {

           System.out.println(xiao);

} else {

          System.out.println("xiao test zhen");

}

以上列出了一下常用的語(yǔ)句的語(yǔ)法樹操作方法,希望對(duì)理解操作語(yǔ)法樹有幫助。筆者也正在研究中,對(duì)編譯原理了解的話,學(xué)起來也就容易多了。

推薦幾本書,看完的話定定會(huì)受益匪淺:《編譯原理(高清龍書中文版)》、《兩周自制腳本語(yǔ)言》、《現(xiàn)代編譯器的Java實(shí)現(xiàn)(第二版)》。

更多關(guān)于java編譯期修改語(yǔ)法樹的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • ReadWriteLock接口及其實(shí)現(xiàn)ReentrantReadWriteLock方法

    ReadWriteLock接口及其實(shí)現(xiàn)ReentrantReadWriteLock方法

    下面小編就為大家?guī)硪黄猂eadWriteLock接口及其實(shí)現(xiàn)ReentrantReadWriteLock方法。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-06-06
  • Spring?MVC數(shù)據(jù)響應(yīng)處理詳解

    Spring?MVC數(shù)據(jù)響應(yīng)處理詳解

    這篇文章主要給大家介紹了關(guān)于Spring?MVC數(shù)據(jù)響應(yīng)處理的相關(guān)資料,本教程詳細(xì)的講解SpringMVC框架的使用,非常詳細(xì)的案例講解,一步一步帶你走入springmvc框架的核心,需要的朋友可以參考下
    2022-05-05
  • Java?webservice的POST和GET請(qǐng)求調(diào)用方式

    Java?webservice的POST和GET請(qǐng)求調(diào)用方式

    這篇文章主要介紹了Java?webservice的POST和GET請(qǐng)求調(diào)用方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-03-03
  • Java視頻斷點(diǎn)上傳的實(shí)現(xiàn)示例

    Java視頻斷點(diǎn)上傳的實(shí)現(xiàn)示例

    斷點(diǎn)續(xù)傳指的是在下載或上傳時(shí),將下載或上傳任務(wù)人為的劃分為幾個(gè)部分,本文主要介紹了Java視頻斷點(diǎn)上傳的實(shí)現(xiàn)示例,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-05-05
  • Java中的泛型詳解

    Java中的泛型詳解

    這篇文章主要介紹了Java中的泛型詳解,本文講解了泛型類或接口、從泛型類派生子類、偽泛型、類型通配符、通配符的上限、通配符的下限、擦除和轉(zhuǎn)換等內(nèi)容,需要的朋友可以參考下
    2015-04-04
  • java 中volatile和lock原理分析

    java 中volatile和lock原理分析

    這篇文章主要介紹了java 中volatile和lock原理分析的相關(guān)資料,需要的朋友可以參考下
    2017-03-03
  • java數(shù)據(jù)庫(kù)數(shù)據(jù)分批讀取的實(shí)現(xiàn)示例

    java數(shù)據(jù)庫(kù)數(shù)據(jù)分批讀取的實(shí)現(xiàn)示例

    在處理大量數(shù)據(jù)時(shí),直接從數(shù)據(jù)庫(kù)一次性讀取所有數(shù)據(jù)可能會(huì)導(dǎo)致內(nèi)存溢出或者性能下降,本文就來介紹一下java數(shù)據(jù)庫(kù)數(shù)據(jù)分批讀取的實(shí)現(xiàn)示例,感興趣的可以了解一下
    2024-01-01
  • Eclipse中常用快捷鍵匯總

    Eclipse中常用快捷鍵匯總

    這篇文章主要介紹了Eclipse中常用快捷鍵,文中介紹的非常詳細(xì),幫助大家更好的利用eclipse開發(fā),感興趣的朋友可以了解下
    2020-07-07
  • java中注解機(jī)制及其原理的詳解

    java中注解機(jī)制及其原理的詳解

    這篇文章主要介紹了java中注解機(jī)制及其原理的詳解的相關(guān)資料,希望通過本文能幫助到大家,讓大家理解掌握這部分內(nèi)容,需要的朋友可以參考下
    2017-10-10
  • Java實(shí)現(xiàn)HTML轉(zhuǎn)為Word的示例代碼

    Java實(shí)現(xiàn)HTML轉(zhuǎn)為Word的示例代碼

    本文以Java代碼為例為大家詳細(xì)介紹如何實(shí)現(xiàn)將HTML文件轉(zhuǎn)為Word文檔(.docx、.doc)。在實(shí)際開發(fā)場(chǎng)景中可參考此方法來轉(zhuǎn)換,感興趣的可以了解一下
    2022-06-06

最新評(píng)論