標籤: 網頁設計公司推薦

  • Java開發中常用jar包整理及使用

    Java開發中常用jar包整理及使用

    本文整理了我自己在Java開發中常用的jar包以及常用的API記錄。

    <!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
            <dependency>
                <groupId>org.apache.commons</groupId>
                <artifactId>commons-lang3</artifactId>
                <version>3.8</version>
            </dependency>
            <!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
            <dependency>
                <groupId>commons-io</groupId>
                <artifactId>commons-io</artifactId>
                <version>2.6</version>
            </dependency>
            <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <version>1.18.8</version>
                <scope>provided</scope>
            </dependency>
            <dependency>
                <groupId>log4j</groupId>
                <artifactId>log4j</artifactId>
                <version>1.2.17</version>
            </dependency>

    common-lang3

    簡介

    一個現在最為常用的jar包,封裝了許多常用的工具包

    依賴:

    <!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-lang3</artifactId>
        <version>3.4</version>
    </dependency>

    主要常見的類如下:

    • 數組工具類 ArrayUtils
    • 日期工具類 DateUtils DateFormatUtils
    • 字符串工具類 StringUtils
    • 数字工具類 NumberUtils
    • 布爾工具類 BooleanUtils
    • 反射相關工具類 FieldUtils、MethodUtils、MemberUtils、TypeUtils、ConstructorUtils
    • 對象工具類 ObjectUtils
    • 序列化工具類 SerializationUtils

    API介紹

    這裏我只介紹經常使用的幾個工具類及方法,ArrayUtils,StringUtils,NumberUtils,DateUtils,其他的請查看官方API文檔吧

    1.ArrayUtils

    方法名 說明
    add
    remove
    clone 複製數組
    addAll
    removeAll 第二個參數傳入需要刪除的下標(可以指定多個下標)
    toObject 把數值(int[],double[])轉為包裝類(Int[],Double[])
    indexOf 在數組按順序查找,找到第一個滿足對應的數值的下標
    lastIndexOf 在數組按順序查找,找到最後一個滿足對應的數值的下標
    contains 數組是否包含某個值
    isEmpty 判斷數組是否為空
    isNotEmpty 判斷數組是否不為空
    reverse 數組反轉
    subarray 指定區間截取數組,區間為半開區間,不包含末尾
    toArray 接收一個多個對象,把這幾個對象轉為對應類型的數組
    toMap 將一個二維數組轉為Map

    2.NumberUtils

    方法名 說明
    min 比較三個數,返回最小值 或比較指定的幾個數,返回最小值
    max 比較三個數,返回最大值 或比較指定的幾個數,返回最大值
    createInt 從傳入的String中創建對應類型的數值,createDouble,createFloat…
    toInt 將指定字符串轉為Int類型,可以選擇指定默認數值,如果字符串為null則返回默認數值,除此之外,還有toDouble,toLong…等轉為不同類型的方法
    compare 比較兩個同類型數值的大小
    isDigits 判斷字符串是否只包含数字
    isParsable 判斷字符串是否可轉換為Long,Int等類型
    isNumber 判斷字符串是否為數值(0x,0X開頭等進制數值)

    3.DateUtils

    方法名 說明
    parseDate 將Date對象轉為字符串
    isSameDay 判斷兩個Dated對象是否為同一天
    isSameDay 判斷兩個Dated對象是否為同一天
    addHour 將指定的Date對象加上指定小時,除此之外,還有addMonth,addDay..等

    DateFormatUtils正如其名,是用來把時間轉為字符串,這裏就不再多說

    4.StringUtils

    方法名 說明
    join 將指定的數組連接成字符串,並添加指定的分割字符
    containOnly 字符串是否只包含某個字符串
    substringBefore 截取指定字符串前面的內容
    substringAfter 截取指定字符串後面的內容(不包括指定字符串)
    substringBetween 截取字符串某區間內容,如substringBetween(“abcde”,”a”,”e”)=”bcd”
    difference 比較兩個字符串,返回兩個字符串不同的內容,具體可以看API文檔給出的示例
    isBlank 判斷字符串是否為空白,null,””,” “這三個結果都是為true
    isEmpty 判斷字符串是否為空(只要不為null,或傳入的String對象的長度不為0即為true)
    countMatches 判斷指定的字符串在某個字符串中出現的次數
    deleteWhitespace 刪除字符串中的空格
    defaultIfBlank 如果字符串為空白,則返回一個指定的默認值(null或某個String)
    defaultIfEmpty 如果字符串為空,則返回一個指定的默認值(null或某個String)
    capitalize 將指定字符串首字母大寫
    abbreviate 將指定字符串的後面三位轉為…
    swapCase 將字符串中的字母大小寫反轉,如aBc變為AbC
    lowerCase 將字符串的字母全部轉為小寫
    upperCase 將字符串的字母全部轉為大寫
    left 取字符串左邊幾個字符,如left(“hello”,3)=”hel”,right與此相反
    leftPad 字符串的長度不夠,則使用指定字符填充指定字符串,如leftPad(“hel”,5,”z”)=”zzhel”,rightPad方法與此相反
    prependIfMissing 指定字符串不以某段字符串開頭,則自動添加開頭,如prependIfMissing(“hello”,”li”)=”lihello”
    prependIfMissing 指定字符串不以某段字符串開頭(忽略大小寫),則自動添加開頭
    getCommonPrefix 獲得多個字符串相同的開頭內容,接收參數為多個字符串
    removeEnd 刪除字符串中結尾(滿足是以某段內容結尾),如removeEnd(“hello”,”llo”)=”he”
    removeEndIgnoreCase 與上面一樣,忽略大小寫
    removeStart 與上面的相反
    remove 刪除字符串中的指定內容,如remove(“hello”,”l”)=”heo”
    removeIgnoreCase 刪除字符串中的指定內容,如remove(“hello”,”l”)=”heo”
    strip 清除字符串開頭和末尾指定的字符(第二個參數為null,用來清除字符串開頭和末尾的空格),如strip(” abcxy”,”xy”)=” abc”,strip(” abcxy”,”yx”)=” abc”
    stripStart 清除字符串開頭指定字符
    stripEnd 清除字符串末尾指定的字符

    common-io

    簡介

    常用的IO流工具包

    <!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
    <dependency>
        <groupId>commons-io</groupId>
        <artifactId>commons-io</artifactId>
        <version>2.6</version>
    </dependency>

    API

    我們主要關心的就是Utils後綴的那幾個類即可,可以看到,common-io庫提供了FileUtils,FileSystemUtils,FileNameUtils,FileFilterUtils,IOUtils

    FileUtils

    • 寫出文件
    • 讀取文件
    • 創建一個有父級文件夾的文件夾
    • 複製文件和文件夾
    • 刪除文件和文件夾
    • URL轉文件
    • 通過過濾器和擴展名來篩選文件和文件夾
    • 比較文件內容
    • 文件最後修改時間
    • 文件校驗

    FileSystemUtils

    關於文件系統的相關操作,如查看C盤的大小,剩餘大小等操作

    IOUtils

    字面意思,是封裝了IO流的各種操作的工具類

    Log4j

    簡介

    Log4J 是 Apache 的一個開源項目,通過在項目中使用 Log4J,我們可以控制日誌信息輸出到控制台、文件、GUI 組件、甚至是數據庫中。

    我們可以控制每一條日誌的輸出格式,通過定義日誌的輸出級別,可以更靈活的控制日誌的輸出過程,方便項目的調試。

    依賴:

    <dependency>
        <groupId>log4j</groupId>
        <artifactId>log4j</artifactId>
        <version>1.2.17</version>
    </dependency>

    結構

    Log4J 主要由 Loggers (日誌記錄器)、Appenders(輸出端)和 Layout(日誌格式化器)組成。

    其中Loggers 控制日誌的輸出級別與日誌是否輸出;
    Appenders 指定日誌的輸出方式(輸出到控制台、文件等);
    Layout 控制日誌信息的輸出格式。

    日誌級別:

    級別 說明
    OFF 最高日誌級別,關閉左右日誌
    FATAL 將會導致應用程序退出的錯誤
    ERROR 發生錯誤事件,但仍不影響系統的繼續運行
    WARN 警告,即潛在的錯誤情形
    INFO 一般和在粗粒度級別上,強調應用程序的運行全程
    DEBUG 一般用於細粒度級別上,對調試應用程序非常有幫助
    ALL 最低等級,打開所有日誌記錄

    我們主要使用這四個:Error>Warn>Info>Debug

    使用

    我們可以使用兩種方式來運行Log4j,一種是java代碼方式,另外一種則是配置文件方式

    例子(Java方式)

    public class Log4JTest {
        public static void main(String[] args) {   
            //獲取Logger對象的實例(傳入當前類)         
            Logger logger = Logger.getLogger(Log4JTest.class);
            //使用默認的配置信息,不需要寫log4j.properties
            BasicConfigurator.configure();
            //設置日誌輸出級別為WARN,這將覆蓋配置文件中設置的級別,只有日誌級別低於WARN的日誌才輸出
            logger.setLevel(Level.WARN);
            logger.debug("這是debug");
            logger.info("這是info");
            logger.warn("這是warn");
            logger.error("這是error");
            logger.fatal("這是fatal");
        }
    }

    例子(配置文件方式)

    上面的例子,我們想要實現打印Log,但是每次都要寫一遍,浪費時間和精力,所以,Log4j提供了另外一種方式來配置好我們的信息

    創建一個名為log4j.properties的文件,此文件需要放在項目的根目錄(約定),如果是maven項目,直接放在resources文件夾中即可

    log4j.properties

    #控制台
    log4j.appender.Console=org.apache.log4j.ConsoleAppender
    log4j.appender.Console.layout=org.apache.log4j.PatternLayout
    log4j.appender.Console.layout.ConversionPattern=%d [%t] %-5p [%c] - %m%n
    
    #log jdbc
    log4j.logger.java.sql.ResultSet=INFO
    log4j.logger.org.apache=WARN
    log4j.logger.java.sql.Connection=DEBUG
    log4j.logger.java.sql.Statement=DEBUG
    log4j.logger.java.sql.PreparedStatement=DEBUG
    
    #log mybatis設置
    #log4j.logger.org.apache.ibatis=DEBUG
    log4j.logger.org.apache.ibatis.jdbc=error
    log4j.logger.org.apache.ibatis.io=info
    log4j.logger.org.apache.ibatis.datasource=info
    
    #springMVC日誌
    log4j.logger.org.springframework.web=WARN
    
    # 文件輸出配置
    log4j.appender.A = org.apache.log4j.DailyRollingFileAppender
    log4j.appender.A.File = D:/log.txt #指定日誌的輸出路徑
    log4j.appender.A.Append = true
    log4j.appender.A.Threshold = DEBUG
    log4j.appender.A.layout = org.apache.log4j.PatternLayout #使用自定義日誌格式化器
    log4j.appender.A.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss}  [ %t:%r ] - [ %p ]  %m%n #指定日誌的輸出格式
    log4j.appender.A.encoding=UTF-8 #指定日誌的文件編碼
    
    #指定日誌的輸出級別與輸出端
    log4j.rootLogger=DEBUG,Console,A
    
    #指定某個包名日誌級別(不能超過上面定義的級別,否則日誌不會輸出)
    log4j.logger.com.wan=DEBUG

    之後使用的話就比較簡單了

    //Logger的初始化(這個推薦定義為全局變量,方便使用)
    Logger logger = Logger.getLogger(Log4JTest.class);
    //輸出Log
    logger.info("這是info");

    參考鏈接:

    lombok

    簡介

    平常我們創建實體類的時候,需要get/set方法,極其麻煩,雖然IDEA等IDE都是有提供了快捷生成,不過,最好的解決方法還是省略不寫

    而lombok就是這樣的一個框架,實現省略get/set方法,當然,lombok的功能不只有此,還有equal,toString方法也可以由此框架自動生成

    lombok的原理是使用註解,之後就會在編譯過程中,給Class文件自動加上get/set等方法

    不過IDEA似乎無法識別,代碼檢查還是會報錯,所以,使用IDEA的時候還得安裝一個插件,在plugin搜索lombok,之後安裝重啟即可,如圖

    之後為Java項目添加依賴

    <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.18.8</version>
        <scope>provided</scope>
    </dependency>

    使用示例

    1.實體類省略get/set
    估計Kotlin中的data關鍵字就是參照着lombok實現的

    //這裏我們只需要為類添加Data註解,就會自動生成對應屬性的get/set方法,toString,equal等方法
    @Data
    public class User {
        private String username;
        private String password;
    }

    2.需要無參構造以及get/set方法

    @Getter
    @Setter
    @NoArgsConstructor
    public class User {
        private String username;
        private String password;
    }

    3.鏈式調用set方法

    @Data
    @Accessors(chain = true)
    public class User {
        private String username;
        private String password;
    }
    
    //使用
    User user = new User();
    user.setUsername("helo").setPassword("123");

    4.參數不為空

    //如果調用此方法,就會抱一個空指針錯誤
    public String print(@NotNull String str){
        ...
    }

    5.只需要toString

    @ToString(callSuper=true, includeFieldNames=true)
    public class User {
        private String username;
        private String password;
        //省略的get/set方法
    }

    6.builder模式創建實體類對象

    @Data
    @Builder
    public class User {
        private String username;
        private String password;
    }
    //使用
    User user1 = User.builder().username("user1").password("123").build();

    7.工具類

    @UtilityClass
    public class MyUtils{
        //會將此方法自動轉為靜態方法
        public void print(String str){
            ...
        }
    }
    //使用
    MyUtils.print("hello");

    8.自動關閉流

    public static void main(String[] args) throws Exception {
        //使用Cleanup會自動調用close方法
        @Cleanup InputStream in = new FileInputStream(args[0]);
        @Cleanup OutputStream out = new FileOutputStream(args[1]);
        byte[] b = new byte[1024];
        while (true) {
            int r = in.read(b);
            if (r == -1) break;
            out.write(b, 0, r);
        }
    }

    9.省略Logger時的初始化

    @Log4j
    @Log
    public class User{
        //會自動添加此語句
        //Logger logger = Logger.getLogger(User.class);
        ...
    }

    參考:

    本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理【其他文章推薦】

    台北網頁設計公司這麼多,該如何挑選?? 網頁設計報價省錢懶人包"嚨底家"

    網頁設計公司推薦更多不同的設計風格,搶佔消費者視覺第一線

    ※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

  • .NET高級特性-Emit(2)類的定義,.NET高級特性-Emit(1)

    .NET高級特性-Emit(2)類的定義,.NET高級特性-Emit(1)

      在上一篇博文發了一天左右的時間,就收到了博客園許多讀者的評論和推薦,非常感謝,我也會及時回復讀者的評論。之後我也將繼續撰寫博文,梳理相關.NET的知識,希望.NET的圈子能越來越大,開發者能了解/深入.NET的本質,將工作做的簡單又高效,拒絕重複勞動,拒絕CRUD。

      ok,咱們開始繼續Emit的探索。在這之前,我先放一下我往期關於Emit的文章,方便讀者閱讀。

      《》

    一、基礎知識

      既然C#作為一門面向對象的語言,所以首當其沖的我們需要讓Emit為我們動態構建類。

      廢話不多說,首先,我們先來回顧一下C#類的內部由什麼東西組成:

      (1) 字段-C#類中保存數據的地方,由訪問修飾符、類型和名稱組成;

      (2) 屬性-C#類中特有的東西,由訪問修飾符、類型、名稱和get/set訪問器組成,屬性的是用來控制類中字段數據的訪問,以實現類的封裝性;在Java當中寫作getXXX()和setXXX(val),C#當中將其變成了屬性這種語法糖;

      (3) 方法-C#類中對邏輯進行操作的基本單元,由訪問修飾符、方法名、泛型參數、入參、出參構成;

      (4) 構造器-C#類中一種特殊的方法,該方法是專門用來創建對象的方法,由訪問修飾符、與類名相同的方法名、入參構成。

      接着,我們再觀察C#類本身又具備哪些東西:

      (1) 訪問修飾符-實現對C#類的訪問控制

      (2) 繼承-C#類可以繼承一個父類,並需要實現父類當中所有抽象的方法以及選擇實現父類的虛方法,還有就是子類需要調用父類的構造器以實現對象的創建

      (3) 實現-C#類可以實現多個接口,並實現接口中的所有方法

      (4) 泛型-C#類可以包含泛型參數,此外,類還可以對泛型實現約束

      以上就是C#類所具備的一些元素,以下為樣例:

    public abstract class Bar
    {
        public abstract void PrintName();
    }
    public interface IFoo<T> { public T Name { get; set; } } //繼承Bar基類,實現IFoo接口,泛型參數T
    public class Foo<T> : Bar, IFoo<T>
      //泛型約束
      where T : struct {
    //構造器 public Foo(T name):base() { _name = name; } //字段 private T _name; //屬性 public T Name { get => _name; set => _name = value; } //方法 public override void PrintName() {
        Console.WriteLine(_name.ToString()); }
    }

      在探索完了C#類及其定義后,我們要來了解C#的項目結構組成。我們知道C#的一個csproj項目最終會對應生成一個dll文件或者exe文件,這一個文件我們稱之為程序集Assembly;而在一個程序集中,我們內部包含和定義了許多命名空間,這些命令空間在C#當中被稱為模塊Module,而模塊正是由一個一個的C#類Type組成。

     

     

     

       所以,當我們需要定義C#類時,就必須首先定義Assembly以及Module,如此才能進行下一步工作。

    二、IL概覽

       由於Emit實質是通過IL來生成C#代碼,故我們可以反向生成,先將寫好的目標代碼寫成cs文件,通過編譯器生成dll,再通過ildasm查看IL代碼,即可依葫蘆畫瓢的編寫出Emit代碼。所以我們來查看以下上節Foo所生成的IL代碼。

      

     

     

       從上圖我們可以很清晰的看到.NET的層級結構,位於樹頂層淺藍色圓點表示一個程序集Assembly,第二層藍色表示模塊Module,在模塊下的均為我們所定義的類,類中包含類的泛型參數、繼承類信息、實現接口信息,類的內部包含構造器、方法、字段、屬性以及它的get/set方法,由此,我們可以開始編寫Emit代碼了

    三、Emit編寫

      有了以上的對C#類的解讀和IL的解讀,我們知道了C#類本身所需要哪些元素,我們就開始根據這些元素來開始編寫Emit代碼了。這裏的代碼量會比較大,請讀者慢慢閱讀,也可以參照以上我寫的類生成il代碼進行比對。

      在Emit當中所有創建類型的幫助類均以Builder結尾,從下錶中我們可以看的非常清楚

    元素中文 元素名稱 對應Emit構建器名稱
    程序集  Assembly AssemblyBuilder
    模塊  Module ModuleBuilder
     Type TypeBuilder
    構造器  Constructor ConstructorBuilder
    屬性  Property PropertyBuilder
    字段  Field FieldBuilder
    方法  Method MethodBuilder

      由於創建類需要從Assembly開始創建,所以我們的入口是AssemblyBuilder

      (1) 首先,我們先引入命名空間,我們以上節Foo類為樣例進行編寫

    using System.Reflection.Emit;

      (2) 獲取基類和接口的類型

    var barType = typeof(Bar);
    var interfaceType = typeof(IFoo<>);

      (3) 定義Foo類型,我們可以看到在定義類之前我們需要創建Assembly和Module

    //定義類
    var assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName("Edwin.Blog.Emit"), AssemblyBuilderAccess.Run);
    var moduleBuilder = assemblyBuilder.DefineDynamicModule("Edwin.Blog.Emit");
    var typeBuilder = moduleBuilder.DefineType("Foo", TypeAttributes.Public | TypeAttributes.Class | TypeAttributes.AutoClass | TypeAttributes.AnsiClass | TypeAttributes.BeforeFieldInit);

      (4) 定義泛型參數T,並添加約束

    //定義泛型參數
    var genericTypeBuilder = typeBuilder.DefineGenericParameters("T")[0];
    //設置泛型約束
    genericTypeBuilder.SetGenericParameterAttributes(GenericParameterAttributes.NotNullableValueTypeConstraint);

      (5) 繼承和實現接口,注意當實現類的泛型參數需傳遞給接口時,需要將泛型接口添加泛型參數后再調用AddInterfaceImplementation方法

    //繼承基類
    typeBuilder.SetParent(barType);
    //實現接口
    typeBuilder.AddInterfaceImplementation(interfaceType.MakeGenericType(genericTypeBuilder));

      (6) 定義字段,因為字段在構造器值需要使用,故先創建

    //定義字段
    var fieldBuilder = typeBuilder.DefineField("_name", genericTypeBuilder, FieldAttributes.Private);

      (7) 定義構造器,並編寫內部邏輯

    //定義構造器
    var ctorBuilder = typeBuilder.DefineConstructor(MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName, CallingConventions.Standard, new Type[] { genericTypeBuilder });
    var ctorIL = ctorBuilder.GetILGenerator();
    //Ldarg_0在實例方法中表示this,在靜態方法中表示第一個參數
    ctorIL.Emit(OpCodes.Ldarg_0);
    ctorIL.Emit(OpCodes.Ldarg_1);
    //為field賦值
    ctorIL.Emit(OpCodes.Stfld, fieldBuilder);
    ctorIL.Emit(OpCodes.Ret);

      (8) 定義Name屬性

    //定義屬性
    var propertyBuilder = typeBuilder.DefineProperty("Name", PropertyAttributes.None, genericTypeBuilder, Type.EmptyTypes);

      (9) 編寫Name屬性的get/set訪問器

    //定義get方法
    var getMethodBuilder = typeBuilder.DefineMethod("get_Name", MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.SpecialName | MethodAttributes.Virtual, CallingConventions.Standard, genericTypeBuilder, Type.EmptyTypes);
    var getIL = getMethodBuilder.GetILGenerator();
    getIL.Emit(OpCodes.Ldarg_0);
    getIL.Emit(OpCodes.Ldfld, fieldBuilder);
    getIL.Emit(OpCodes.Ret);
    typeBuilder.DefineMethodOverride(getMethodBuilder, interfaceType.GetProperty("Name").GetGetMethod()); //實現對接口方法的重載
    propertyBuilder.SetGetMethod(getMethodBuilder); //設置為屬性的get方法
    //定義set方法
    var setMethodBuilder = typeBuilder.DefineMethod("set_Name", MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.SpecialName | MethodAttributes.Virtual, CallingConventions.Standard, null, new Type[] { genericTypeBuilder });
    var setIL = setMethodBuilder.GetILGenerator();
    setIL.Emit(OpCodes.Ldarg_0);
    setIL.Emit(OpCodes.Ldarg_1);
    setIL.Emit(OpCodes.Stfld, fieldBuilder);
    setIL.Emit(OpCodes.Ret);
    typeBuilder.DefineMethodOverride(setMethodBuilder, interfaceType.GetProperty("Name").GetSetMethod()); //實現對接口方法的重載
    propertyBuilder.SetSetMethod(setMethodBuilder); //設置為屬性的set方法

       (10) 定義並實現PrintName方法

    //定義方法
    var printMethodBuilder = typeBuilder.DefineMethod("PrintName", MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.Virtual, CallingConventions.Standard, null, Type.EmptyTypes);
    var printIL = printMethodBuilder.GetILGenerator();
    printIL.Emit(OpCodes.Ldarg_0);
    printIL.Emit(OpCodes.Ldflda, fieldBuilder);
    printIL.Emit(OpCodes.Constrained, genericTypeBuilder);
    printIL.Emit(OpCodes.Callvirt, typeof(object).GetMethod("ToString", Type.EmptyTypes));
    printIL.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) }));
    printIL.Emit(OpCodes.Ret);
    //實現對基類方法的重載
    typeBuilder.DefineMethodOverride(printMethodBuilder, barType.GetMethod("PrintName", Type.EmptyTypes));

      (11) 創建類

    var type = typeBuilder.CreateType(); //netstandard中請使用CreateTypeInfo().AsType()

      (12) 調用

    var obj = Activator.CreateInstance(type.MakeGenericType(typeof(DateTime)), DateTime.Now);
    (obj as Bar).PrintName();
    Console.WriteLine((obj as IFoo<DateTime>).Name);

    四、應用

      上面的樣例僅供學習只用,無法運用在實際項目當中,那麼,Emit構建類在實際項目中我們可以有什麼應用,提高我們的編碼效率

      (1) 動態DTO-當我們需要將實體映射到某個DTO時,可以用動態DTO來代替你手寫的DTO,選擇你需要的字段回傳給前端,或者前端把他想要的字段傳給後端

      (2) DynamicLinq-我的第一篇博文有個讀者提到了表達式樹,而linq使用的正是表達式樹,當表達式樹+Emit時,我們就可以用像SQL或者GraphQL那樣的查詢語句實現動態查詢

      (3) 對象合併-我們可以編寫實現一個像js當中Object.assign()一樣的方法,實現對兩個實體的合併

      (4) AOP動態代理-AOP的核心就是代理模式,但是與其對應的是需要手寫代理類,而Emit就可以幫你動態創建代理類,實現切面編程

      (5) …

    五、小結

      對於Emit,確實初學者會對其感到複雜和難以學習,但是只要搞懂其中的原理,其實最終就是C#和.NET語言的本質所在,在學習Emit的同時,也是在鍛煉你的基本功是否紮實,你是否對這門語言精通,是否有各種簡化代碼的應用。

      保持學習,勇於實踐;Write Less,Do More;作者之後還會繼續.NET高級特性系列,感謝閱讀!

    本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理【其他文章推薦】

    網頁設計公司推薦更多不同的設計風格,搶佔消費者視覺第一線

    ※廣告預算用在刀口上,網站設計公司幫您達到更多曝光效益

    ※自行創業 缺乏曝光? 下一步"網站設計"幫您第一時間規劃公司的門面形象

  • NEDO、夏普和豐田攜手,高效太陽能電動車 7 月下旬上路測試

    NEDO、夏普和豐田攜手,高效太陽能電動車 7 月下旬上路測試

    豐田的插電式油電混合車 Prius PHV 將再出發。最近夏普、豐田以及日本新能源產業技術總合開發機構(NEDO)攜手合作,在 Prius PHV 裝設 34% 超高效率太陽能板,推出全新規模的太陽能油電混合車,預計將在 7 月下旬上路測試。

    Prius PHV 是從 Prius 衍伸出來的插電式油電車,除了一般的鋰離子充電系統,還可以裝設轉換效率達 22%、容量共 180W 的太陽能板,只不過其在日照充裕時只能增加 6.1公里的行駛距離,著實不夠。

    而現在該團隊決定換一種太陽能光電技術,NEDO 透過磷化銦鎵(InGaP)、砷化鎵(GaAs)、砷化銦鎵(InGaAs)等三五族半導體,研發出轉換效率超越 34% 的超高效率三接面(Triple-junction)太陽能板。

    這些僅有 0.03mm 太陽能板將會裝設在引擎蓋、車頂與後車箱之上,也因為搭載的太陽能板轉換效率大幅提升,發電容量也不可同日而語,已從 180W 躍升至 860W,車輛靜止狀態下可增加 44.5 的續航距離,是過去 Prius PHV 車型的 7 倍左右,且車輛行駛時也能提供電力,將續航距離提升至 56.3 公里。

    其中該計畫是由 NEDO 主導,2016 年 4 月時 NEDO 成立車載太陽戰略委員會,希望能透過太陽能系統,找出緩解交通能源與環境問題的解決方案,而團隊目前盼望能在有限的裝設空間下,利用轉換效率高達 30% 的太陽能板,實現 1KW 的發電潛力。

    目前團隊將會在本月下旬在日本東京、愛知縣豐田市的道路、高速公路上進行測試,測試時間將在 2020 年 2 月底結束。 NEDO、豐田與夏普將能共享實驗測試的全部數據,也將會進一步評估能降低多少二氧化碳排放量、是否真的能降低充電次數以及大眾的接受度等等。

    隨著太陽能與電動車技術日新月異,未來將會有愈來愈多新奇有趣車型出爐,雖然些車輛的外型或是性能,還無法跟傳統燃油車相比,但這些都是綠色能源車的新嘗試。就好比先前荷蘭新創公司 Lightyear 也宣布,首款太陽能電動原型車 Lightyear One 預計在 2021 年開始量產上市,充電一次就能跑 725 公里。

    (合作媒體:。首圖來源:)

    延伸閱讀:

    本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

    【其他文章推薦】

    台北網頁設計公司這麼多,該如何挑選?? 網頁設計報價省錢懶人包"嚨底家"

    網頁設計公司推薦更多不同的設計風格,搶佔消費者視覺第一線

    ※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

  • 區塊鏈成重要突破口,與幣圈無關卻與5G有關

    區塊鏈成重要突破口,與幣圈無關卻與5G有關

      幾乎是一夜之間,區塊鏈就成了更熱門的話題,此前,如果我們還在說“物聯網、大數據、雲計算、人工智能和 5G”,那麼,以後這一長串的背後可能就要加上“區塊鏈”。

      誠然,國家將區塊鏈當成戰略來發展,並“要把區塊鏈作為核心技術自主創新的重要突破口,明確主攻方向,加大投入力度,着力攻克一批關鍵核心技術,加快推動區塊鏈技術和產業創新發展”,這對整個區塊鏈產業都是巨大的利好,但是,這種利好卻實實在在與現在網絡上那些頂着區塊鏈帽子實際卻是在搞傳銷的“幣”們,毫無關係。如果有關係,那也一定是負面。

      在國內,區塊鏈技術佔據優勢的公司依然是 BAT,特別是阿里巴巴和螞蟻金服。在 2018 年的世界互聯網大會上,螞蟻金服“自主可控金融級商用區塊鏈平台”與“阿里雲 supET 工業互聯網平台”同時入選 15 項世界互聯網領先科技成果之列。前者的區塊鏈因素顯而易見,後者實際上也在由區塊鏈提供製造生產質量追溯和供應鏈管理服務。

      據全球知名智能信息服務機構科睿唯安公布信息,截至 2019 年 4 月 30 日,阿里巴巴以 290 件區塊鏈專利方案數量穩居全球第一。結合權威知識產權產業媒體 IPRdaily 過去兩年發布的“全球區塊鏈專利企業排行榜”显示,阿里巴巴申請的區塊鏈專利數量已經連續三年全球第一。2019 上半年全球區塊鏈企業發明專利排行榜(TOP100) 中,阿里巴巴以 322 件專利位列第一,中國平安以 274 件專利排名第二,Nchain 以 241 件專利排名第三。此外,百度( 7 名)、騰訊( 13 名)、京東( 14 名)、華為( 28 名)、獵豹( 40 名)、中國移動( 44 名)等均榜上有名。

      從上面的數據可以看出來,真正在區塊鏈的研究上佔據優勢且不斷應用的,沒有一個是“發幣”的,都是實實在在的在落地。

      當然了,也許與幣有關。此前有消息傳言,央行可能將在未來幾個月內正式推出國家支持的数字貨幣“DCEP”,初期將向中國工商銀行、中國建設銀行、中國銀行、中國農業銀行、阿里巴巴、騰訊以及銀聯七家機構發行。如果成行,那將是世界上是首個法定数字貨幣,意義深遠。

      在官方發布的新聞中,將區塊鏈發展方向定位為四個方面:

      1、要探索“區塊鏈+”在民生領域的運用,积極推動區塊鏈技術在教育、就業、養老、精準脫貧、醫療健康、商品防偽、食品安全、公益、社會救助等領域的應用,為人民群眾提供更加智能、更加便捷、更加優質的公共服務。

      2016 年,螞蟻金服聯合中國紅十字基金會等公益機構上線區塊鏈試驗項目,使捐款人可以追蹤善款的完整流轉情況。2017 年 3 月,支付寶愛心捐贈平台全面引入區塊鏈技術,所有捐贈數據上鏈。實現了實時賬目公示,有助於解決公益財務透明的“痛點”。螞蟻金服公益運用區塊鏈技術追蹤籌款,建立起第三方公示體系區塊鏈資金流公示,為公益機構進行數據統計、項目執行跟蹤提供便利。區塊鏈具有不可篡改的特性,任何寫入區塊鏈的記錄均不能更改,可以供公眾監督及審計。而“區塊鏈+公益”正是利用這一特性,發揮公眾賬本的價值,不論用戶是捐十塊、二十塊還是幾百塊,讓用戶所獻出的每一筆都記錄在區塊鏈上,有跡可循,持續追溯。

      2016 年 10 月,阿里與微軟、小蟻、法大大等合作開發“法鏈”,推出基於阿里雲平台的郵箱存證產品,通過法鏈上備份的电子郵件和雲服務,阿里將使中國法院能大規模採用数字證據郵件。

      2017 年 3 月,阿里巴巴與普華永道合作,打造可追溯的跨境食品供應鏈,用於跟蹤產品從生產者到消費者之間的整個流程。

      2017 年 8 月,阿里健康與江蘇常州市合作推出我國首個基於醫療場景的區塊鏈應用――“醫聯體+區塊鏈”試點項目。

      2017 年 10 月 11 日,螞蟻金服 CTO 程立在螞蟻金服金融科技開放峰會上首度披露未來的技術布局――“BASIC”戰略,其中的B對應的就是區塊鏈(Blockchain),同時,技術實驗室宣布開放區塊鏈技術,支持進口食品安全溯源、商品正品溯源等,第一個落地場景將是海外奶粉品牌的追蹤,先是產自澳洲、新西蘭的 26 個品牌的奶粉。2017 年 11 月 24 日,天貓國際宣布升級全球原產地溯源計劃,未來將覆蓋全球 63 個國家和地區,3700 個品類,14500 個海外品牌,也將向全行業開放,賦能整個行業。2018 年 2 月,菜鳥與天貓國際官方消息,已啟用區塊鏈技術跟蹤、上傳、查證跨境進口商品的物流全鏈路信息,涵蓋生產、運輸、通關、報檢、第三方檢驗等商品進口全流程,為每個跨境進口商品打上獨一無二的“身份證”,供消費者查詢驗證。

      騰訊旗下的微眾銀行於 2016 年 6 月開發出面向金融業的聯盟鏈雲服務 BaaS,並在 2017 年 1 月落地了第一個商業場景,即微黃金項目。微黃金是騰訊的一項在線黃金交易服務,用戶可以在微信低門檻靈活購買黃金,其背後正是由騰訊開發底層基礎架構的聯盟鏈。騰訊、工商銀行等多個節點共同參与記帳。2018 年 4 月底,騰訊發布第一款區塊鏈遊戲《一起來捉妖》,試圖通過區塊鏈技術保障了遊戲稀有內容投放的公開公平性,同時用戶可以將稀有妖怪上鏈永久保存。

      2017 年 12 月,沃爾瑪、京東、IBM、清華大學电子商務交易技術國家工程實驗室共同宣布成立安全食品區塊鏈溯源聯盟,運用區塊鏈技術搭建“京東區塊鏈防偽追溯開放平台”。該平台推出之後,用戶只需打開京東 APP 找到購物訂單,通過“一鍵溯源”或直接掃描產品溯源碼,即可獲取溯源信息。

      2018 年 10 月,百度正式發布自主研發的區塊鏈網絡系統——超級鏈。同時,宣布與海南省政府合作,區塊鏈實驗室及度鏈公司落戶海南,並推出“區塊鏈+大閘蟹溯源”應用。

      2、要推動區塊鏈底層技術服務和新型智慧城市建設相結合,探索在信息基礎設施、智慧交通、能源電力等領域的推廣應用,提升城市管理的智能化、精準化水平。

      5 月 22 日,上海、浙江、江蘇、安徽 4 地法院成立全國首個區域司法鏈,實現從起訴到執行全程上鏈,極大提高了訴訟效率和法院公信力,降低訴訟成本。最早引入區塊鏈技術的杭州互聯網法院,上鏈半年,其知識產權糾紛案件的調撤率上升至 95.3%。

      2017 年 5 月,阿里投資 Symbiont,該公司致力於利用區塊鏈技術打造一個發行和交易智能證券的平台。此外,深圳財富文化集團已經打造了一個文化產權交易的區塊鏈平台,並與螞蟻雙鏈打通,解決文化藝術品流通、交易和一系列金融服務。

      2017 年 11 月 8 日,阿里巴巴集團、螞蟻金服集團與雄安新區簽署了戰略合作協議,阿里巴巴與螞蟻金服將承建数字雄安區塊鏈實施平台。

      另外,國網電商公司已建成國家電網公司系統內首個司法級可信區塊鏈公共服務平台,作為唯一央企與北京互聯網法院“天平鏈”互信互通,掛牌工信部區塊鏈重點實驗室電力應用實驗基地,參与首個區塊鏈國家標準制定,實現了區塊鏈技術在電力積分通兌、光伏簽約、票據繳費、电子發票等多場景落地應用。

      3、要利用區塊鏈技術促進城市間在信息、資金、人才、徵信等方面更大規模的互聯互通,保障生產要素在區域內有序高效流動。

      在 9 月末舉行的雲棲大會·螞蟻區塊鏈生態峰會上,螞蟻金服集團副總裁蔣國飛透露,螞蟻區塊鏈已落地 40 多個應用。含括跨境支付、供應鏈金融、通用溯源、电子票據等多個行業領域。並於同期宣布了與全球最大的種子和農藥公司拜耳合作,應用方向進一步擴展。

      螞蟻金服 8 月份宣布,基於區塊鏈技術的供應鏈協作網絡——螞蟻區塊鏈“雙鏈通”全面升級開放。這一服務運用區塊鏈技術可解決供應鏈金融中的信任難題,同時讓小微商家也能享受高效便捷的金融服務。目前,這一模式已在成都率先應用。通過與成都商業銀行、成都中小企業融資擔保公司的合作,“雙鏈通”完成了供應鏈金融的全鏈路覆蓋。上鏈后,整個融資流轉過程清晰留痕、不可篡改,所有參与方都要通過“雙鏈通”進行身份核實和意願確認,数字簽名實時上鏈,杜絕了資金挪用等風險。

      4、要探索利用區塊鏈數據共享模式,實現政務數據跨部門、跨區域共同維護和利用,促進業務協同辦理,深化“最多跑一次”改革,為人民群眾帶來更好的政務服務體驗。

      3 月,杭州地鐵聯合支付寶、螞蟻區塊鏈推出了區塊鏈电子發票。全程手機操作,耗時不到 10 秒,上班族再也不用前往窗口排隊取票了。支付寶聯合雲南省相關部門,在醫療、教育等多個民生服務場景落地區塊鏈电子票據。從地鐵电子發票到法院訴訟案件,再到电子票據平台,螞蟻區塊鏈在過去近 3 年時間里,相繼落地了 40 多個場景。其中長三角佔比超過一半。“上鏈”后長三角人辦事效率大大提升,不少事項可享受“秒級”服務。

      我們看到,在 5G 時代,無差別計算能力的流通成本會大幅下降,無差別計算能力是 AI 最重要的勞動要素,而區塊鏈就是 AI 最重要的勞動要素。阿里巴巴達摩院在《2019 十大科技趨勢》中提到,5G 和區塊鏈是未來十年的發展方向。《福布斯》發布的《2020 十大科技趨勢》也提到,5G 和區塊鏈都將於 2020 年崛起,未來與人們日常生活相關的每一個行業都會被變革。還是那句話,“誰能把當前的技術和資源用到最充分,誰就是這個時代的最強者”,也許 5G 的流量充沛,正是區塊鏈的黃金歲月。

    本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理【其他文章推薦】

    網頁設計公司推薦更多不同的設計風格,搶佔消費者視覺第一線

    ※廣告預算用在刀口上,網站設計公司幫您達到更多曝光效益

    ※自行創業 缺乏曝光? 下一步"網站設計"幫您第一時間規劃公司的門面形象

  • 滴滴每天處理超4875TB數據 基於AI的需求預估準確率達85%

    滴滴每天處理超4875TB數據 基於AI的需求預估準確率達85%

      作者:行者崟濤

      【TechWeb】在 2019 博世智能出行大會上,滴滴旗下小桔車服車聯網業務負責人黃智信表示,滴滴大概每天處理超過 106TB 的軌跡數據,4875TB 的綜合數據,通過 AI 和大數據技術,可以進行叫車供給需求 15 分鐘后的預測,目前準確率達到 85%,派單導航 ETA 誤差率小於 15%,此外還有很多的安全功能等等。

      過去都是通過手機把車和人連接起來,目前滴滴也在做一些探索,如何更好的結合車輛相關數據,實現智能充電、智能維保和派單系統的結合,以更好地提高車輛運營效率和司機體驗。

      黃智信也提出,滴滴也希望可以跟更多產業鏈上下游合作夥伴一起,在數據、技術、產品等方面實現更加開放、深度的合作,為司機和乘客提供更為安全、便捷、舒適的體驗,更好的鼓勵安全、良好的駕駛行為。

    本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理【其他文章推薦】

    台北網頁設計公司這麼多,該如何挑選?? 網頁設計報價省錢懶人包"嚨底家"

    網頁設計公司推薦更多不同的設計風格,搶佔消費者視覺第一線

    ※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

  • Python 命令行之旅:深入 click 之子命令篇

    Python 命令行之旅:深入 click 之子命令篇

    作者:HelloGitHub-Prodesire

    HelloGitHub 的《講解開源項目》系列,項目地址:https://github.com/HelloGitHub-Team/Article

    一、前言

    在上兩篇文章中,我們介紹了 click 中的”參數“和“選項”,本文將繼續深入了解 click,着重講解它的“命令”和”組“。

    本系列文章默認使用 Python 3 作為解釋器進行講解。
    若你仍在使用 Python 2,請注意兩者之間語法和庫的使用差異哦~

    二、命令和組

    Click 中非常重要的特性就是任意嵌套命令行工具的概念,通過 和 (實際上是 )來實現。

    所謂命令組就是若干個命令(或叫子命令)的集合,也成為多命令。

    2.1 回調調用

    對於一個普通的命令來說,回調發生在命令被執行的時候。如果這個程序的實現中只有命令,那麼回調總是會被觸發,就像我們在上一篇文章中舉出的所有示例一樣。不過像 --help 這類選項則會阻止進入回調。

    對於組和多個子命令來說,情況略有不同。回調通常發生在子命令被執行的時候:

    @click.group()
    @click.option('--debug/--no-debug', default=False)
    def cli(debug):
        click.echo('Debug mode is %s' % ('on' if debug else 'off'))
    
    @cli.command()  # @cli, not @click!
    def sync():
        click.echo('Syncing')

    執行效果如下:

    Usage: tool.py [OPTIONS] COMMAND [ARGS]...
    
    Options:
      --debug / --no-debug
      --help                Show this message and exit.
    
    Commands:
      sync
    
    $ tool.py --debug sync
    Debug mode is on
    Syncing

    在上面的示例中,我們將函數 cli 定義為一個組,把函數 sync 定義為這個組內的子命令。當我們調用 tool.py --debug sync 命令時,會依次觸發 clisync 的處理邏輯(也就是命令的回調)。

    2.2 嵌套處理和上下文

    從上面的例子可以看到,命令組 cli 接收的參數和子命令 sync 彼此獨立。但是有時我們希望在子命令中能獲取到命令組的參數,這就可以用 來實現。

    每當命令被調用時,click 會創建新的上下文,並鏈接到父上下文。通常,我們是看不到上下文信息的。但我們可以通過 裝飾器來顯式讓 click 傳遞上下文,此變量會作為第一個參數進行傳遞。

    @click.group()
    @click.option('--debug/--no-debug', default=False)
    @click.pass_context
    def cli(ctx, debug):
        # 確保 ctx.obj 存在並且是個 dict。 (以防 `cli()` 指定 obj 為其他類型
        ctx.ensure_object(dict)
    
        ctx.obj['DEBUG'] = debug
    
    @cli.command()
    @click.pass_context
    def sync(ctx):
        click.echo('Debug is %s' % (ctx.obj['DEBUG'] and 'on' or 'off'))
    
    if __name__ == '__main__':
        cli(obj={})

    在上面的示例中:

    • 通過為命令組 cli 和子命令 sync 指定裝飾器 click.pass_context,兩個函數的第一個參數都是 ctx 上下文
    • 在命令組 cli 中,給上下文的 obj 變量(字典)賦值
    • 在子命令 sync 中通過 ctx.obj['DEBUG'] 獲得上一步的參數
    • 通過這種方式完成了從命令組到子命令的參數傳遞

    2.3 不使用命令來調用命令組

    默認情況下,調用子命令的時候才會調用命令組。而有時你可能想直接調用命令組,通過指定 click.groupinvoke_without_command=True 來實現:

    @click.group(invoke_without_command=True)
    @click.pass_context
    def cli(ctx):
        if ctx.invoked_subcommand is None:
            click.echo('I was invoked without subcommand')
        else:
            click.echo('I am about to invoke %s' % ctx.invoked_subcommand)
    
    @cli.command()
    def sync():
        click.echo('The subcommand')

    調用命令有:

    $ tool
    I was invoked without subcommand
    $ tool sync
    I am about to invoke sync
    The subcommand

    在上面的示例中,通過 ctx.invoked_subcommand 來判斷是否由子命令觸發,針對兩種情況打印日誌。

    2.4 自定義命令組/多命令

    除了使用 來定義命令組外,你還可以自定義命令組(也就是多命令),這樣你就可以延遲加載子命令,這會很有用。

    自定義多命令需要實現 list_commandsget_command 方法:

    import click
    import os
    
    plugin_folder = os.path.join(os.path.dirname(__file__), 'commands')
    
    class MyCLI(click.MultiCommand):
    
        def list_commands(self, ctx):
            rv = []  # 命令名稱列表
            for filename in os.listdir(plugin_folder):
                if filename.endswith('.py'):
                    rv.append(filename[:-3])
            rv.sort()
            return rv
    
        def get_command(self, ctx, name):
            ns = {}
            fn = os.path.join(plugin_folder, name + '.py')  # 命令對應的 Python 文件
            with open(fn) as f:
                code = compile(f.read(), fn, 'exec')
                eval(code, ns, ns)
            return ns['cli']
    
    cli = MyCLI(help='This tool\'s subcommands are loaded from a '
                'plugin folder dynamically.')
    
    # 等價方式是通過 click.command 裝飾器,指定 cls=MyCLI
    # @click.command(cls=MyCLI)
    # def cli():
    #     pass
    
    if __name__ == '__main__':
        cli()

    2.5 合併命令組/多命令

    當有多個命令組,每個命令組中有一些命令,你想把所有的命令合併在一個集合中時,click.CommandCollection 就派上了用場:

    
    @click.group()
    def cli1():
        pass
    
    @cli1.command()
    def cmd1():
        """Command on cli1"""
    
    @click.group()
    def cli2():
        pass
    
    @cli2.command()
    def cmd2():
        """Command on cli2"""
    
    cli = click.CommandCollection(sources=[cli1, cli2])
    
    if __name__ == '__main__':
        cli()

    調用命令有:

    $ cli --help
    Usage: cli [OPTIONS] COMMAND [ARGS]...
    
    Options:
      --help  Show this message and exit.
    
    Commands:
      cmd1  Command on cli1
      cmd2  Command on cli2

    從上面的示例可以看出,cmd1cmd2 分別屬於 cli1cli2,通過 click.CommandCollection 可以將這些子命令合併在一起,將其能力提供個同一個命令程序。

    Tips:如果多個命令組中定義了同樣的子命令,那麼取第一個命令組中的子命令。

    2.6 鏈式命令組/多命令

    有時單級子命令可能滿足不了你的需求,你甚至希望能有多級子命令。典型地,setuptools 包中就支持多級/鏈式子命令: setup.py sdist bdist_wheel upload。在 click 3.0 之後,實現鏈式命令組變得非常簡單,只需在 click.group 中指定 chain=True

    @click.group(chain=True)
    def cli():
        pass
    
    
    @cli.command('sdist')
    def sdist():
        click.echo('sdist called')
    
    
    @cli.command('bdist_wheel')
    def bdist_wheel():
        click.echo('bdist_wheel called')

    調用命令則有:

    $ setup.py sdist bdist_wheel
    sdist called
    bdist_wheel called

    2.7 命令組/多命令管道

    鏈式命令組中一個常見的場景就是實現管道,這樣在上一個命令處理好后,可將結果傳給下一個命令處理。

    實現命令組管道的要點是讓每個命令返回一個處理函數,然後編寫一個總的管道調度函數(並由 MultiCommand.resultcallback() 裝飾):

    @click.group(chain=True, invoke_without_command=True)
    @click.option('-i', '--input', type=click.File('r'))
    def cli(input):
        pass
    
    @cli.resultcallback()
    def process_pipeline(processors, input):
        iterator = (x.rstrip('\r\n') for x in input)
        for processor in processors:
            iterator = processor(iterator)
        for item in iterator:
            click.echo(item)
    
    @cli.command('uppercase')
    def make_uppercase():
        def processor(iterator):
            for line in iterator:
                yield line.upper()
        return processor
    
    @cli.command('lowercase')
    def make_lowercase():
        def processor(iterator):
            for line in iterator:
                yield line.lower()
        return processor
    
    @cli.command('strip')
    def make_strip():
        def processor(iterator):
            for line in iterator:
                yield line.strip()
        return processor

    在上面的示例中:

    • cli 定義為了鏈式命令組,並且指定 invoke_without_command=True,也就意味着可以不傳子命令來觸發命令組
    • 定義了三個命令處理函數,分別對應 uppercaselowercasestrip 命令
    • 在管道調度函數 process_pipeline 中,將輸入 input 變成生成器,然後調用處理函數(實際輸入幾個命令,就有幾個處理函數)進行處理

    2.8 覆蓋默認值

    默認情況下,參數的默認值是從通過裝飾器參數 default 定義。我們還可以通過 Context.default_map 上下文字典來覆蓋默認值:

    @click.group()
    def cli():
        pass
    
    @cli.command()
    @click.option('--port', default=8000)
    def runserver(port):
        click.echo('Serving on http://127.0.0.1:%d/' % port)
    
    if __name__ == '__main__':
        cli(default_map={
            'runserver': {
                'port': 5000
            }
        })

    在上面的示例中,通過在 cli 中指定 default_map 變可覆蓋命令(一級鍵)的選項(二級鍵)默認值(二級鍵的值)。

    我們還可以在 click.group 中指定 context_settings 來達到同樣的目的:

    
    CONTEXT_SETTINGS = dict(
        default_map={'runserver': {'port': 5000}}
    )
    
    @click.group(context_settings=CONTEXT_SETTINGS)
    def cli():
        pass
    
    @cli.command()
    @click.option('--port', default=8000)
    def runserver(port):
        click.echo('Serving on http://127.0.0.1:%d/' % port)
    
    if __name__ == '__main__':
        cli()

    調用命令則有:

    $ cli runserver
    Serving on http://127.0.0.1:5000/

    三、總結

    本文首先介紹了命令的回調調用、上下文,再進一步介紹命令組的自定義、合併、鏈接、管道等功能,了解到了 click 的強大。而命令組中更加高階的能力()則可看官方文檔進一步了解。

    我們通過介紹 click 的參數、選項和命令已經能夠完全實現命令行程序的所有功能。而 click 還為我們提供了許多錦上添花的功能,比如實用工具、參數自動補全等,我們將在下節詳細介紹。

    『講解開源項目系列』——讓對開源項目感興趣的人不再畏懼、讓開源項目的發起者不再孤單。跟着我們的文章,你會發現編程的樂趣、使用和發現參与開源項目如此簡單。歡迎留言聯繫我們、加入我們,讓更多人愛上開源、貢獻開源~

    本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理【其他文章推薦】

    ※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!!

    網頁設計一頭霧水??該從何著手呢? 找到專業技術的網頁設計公司,幫您輕鬆架站!

    ※想知道最厲害的台北網頁設計公司推薦台中網頁設計公司推薦專業設計師”嚨底家”!!

  • Class文件結構全面解析(下)

    Class文件結構全面解析(下)

    接上回書

    書接,分享了Class文件的主要構成,同時也詳細分析了魔數、次版本號、主版本號、常量池集合、訪問標誌的構造,接下來我們就繼續學習。

    歡迎關注微信公眾號:萬貓學社,每周一分享Java技術乾貨。

    類索引和父類索引

    類索引(this_class)和父類索引(super_class)都是一個u2類型的數據,類索引用於確定這個類的全限定名,父類索引用於確定這個類的父類全限定名。由於java語言不允許多重繼承,所以父類索引只有一個。

    類索引和父類索引各自指向常量池中類型為CONSTANT_Class_info的類描述符,再通過類描述符中的索引值找到常量池中類型為CONSTANT_Utf8_info的字符串。再來看一下之前的Class文件例子:

    歡迎關注微信公眾號:萬貓學社,每周一分享Java技術乾貨。

    結合之前javap分析出來的常量池內容:

       #3 = Class         #17        // OneMoreStudy
       #4 = Class         #18        // java/lang/Object
      #17 = Utf8          OneMoreStudy
      #18 = Utf8          java/lang/Object

    類索引為0x0003,去常量池裡找索引為3的類描述符,類描述符中的索引為17,再去找索引為17的字符串,就是“OneMoreStudy”。

    父類索引為0x0004,去常量池裡找索引為4的類描述符,類描述符中的索引為18,再去常量池裡找索引為18的字符串,就是“java/lang/Object”。

    歡迎關注微信公眾號:萬貓學社,每周一分享Java技術乾貨。

    接口索引集合

    接口索引集合(interface)是一組u2類型的數據的集合,由於java語言允許實現多個接口,所以接口索引也有多個,它們按照implements語句后的接口順序從左到右依次排列在接口索引集合中。接口索引集合的第一項數據是接口集合計數值(interfaces_count),表示有多少接口索引。如果該類沒有實現任何接口,那麼該計數值為0,後面的接口索引表不佔任何字節。之前的例子OneMoreStudy類沒有實現任何接口,所以接口集合計數值就是0,如下圖:

    歡迎關注微信公眾號:萬貓學社,每周一分享Java技術乾貨。

    字段表集合

    字段表(field_info)是用來描述接口或類中聲明的變量。包括類級變量(靜態變量)和實例級變量(成員變量),但是不包括在方法內部聲明的局部變量。具體結構如下錶:

    類型 名稱 數量 描述
    u2 access_flags 1 字段的訪問標誌
    u2 name_index 1 字段的簡單名稱索引
    u2 descriptor_index 1 字段的描述符索引
    u2 attributes_count 1 字段的屬性計數值
    attribute_info attributes attributes_count 字段的屬性

    字段表中的access_flags,和類的access_flags是非常類似的,但是標識和含義是不一樣的。具體如下錶:

    標誌名稱 標誌值 含義
    ACC_PUBLIC 0x0001 字段是否public
    ACC_PRIVATE 0x0002 字段是否private
    ACC_PROTECTED 0x0004 字段是否protected
    ACC_STATIC 0x0008 字段是否static
    ACC_FINAL 0x0010 字段是否為final
    ACC_VOLATILE 0x0040 字段是否volatile
    ACC_TRANSIENT 0x0080 字段是否transient
    ACC_SYNTHETIC 0x1000 字段是否由編譯器自動產生的
    ACC_ENUM 0x4000 字段是否enum

    歡迎關注微信公眾號:萬貓學社,每周一分享Java技術乾貨。

    這裏提到了簡單名稱、描述符,和全限定名有什麼區別呢?稍微說一下。

    簡單名稱是沒有類型和參數修飾的方法或字段名稱,比如OneMoreStudy類中的number字段和plusOne()方法的簡單名稱分別是“number”和“plusOne”。

    全限定名是把類全名中的“.”替換成“/”就可以了,比如java.lang.Object類的全限定名就是“java/lang/Object”。

    描述符是用來描述字段的數據類型、方法的參數列表(包括數量、類型以及順序)和返回值。基礎數據類型和無返回的void類型都有一個大寫字母表示,對象類型用字符L加對象的全限定名來表示,如下錶:

    標識字符 含義
    B 基本類型byte
    C 基本類型char
    D 基本類型double
    F 基本類型float
    I 基本類型int
    J 基本類型long
    S 基本類型short
    Z 基本類型boolean
    V 特殊類型void
    L 對象類型 如 Ljava/lang/Object

    對於數組類型,每一維度使用一個前置的“[”字符來描述,比如java.lang.Object[][]的二維數據,就是“[[Ljava/lang/Object”。在描述方法時,按照先參數列表,后返回值的順序描述,參數列表按照嚴格順序放在“()”值中,比如boolean equals(Object anObject),就是“(Ljava/lang/Object)B”。

    歡迎關注微信公眾號:萬貓學社,每周一分享Java技術乾貨。

    再來看一下之前的Class文件例子:

    OneMoreStudy類中只有一個字段number,所以字段計數值為0x0001。字段number只被private修飾,沒有其他修飾,所以字段的訪問標誌位為0x0002。字段的簡單名稱索引是0x0005,去常量池中找索引為5的字符串,為“number”。字段的描述符索引為0x0006,去常量池中找索引為6的字符串,為“I”,是基本類型int。以下是常量池相關內容:

       #5 = Utf8          number
       #6 = Utf8          I

    字段number的屬性計數值為0x0000,也就是沒有需要額外描述的信息。

    字段表集合中不會列出從父類或者父接口中繼承而來的字段,但有可能列出原版Java代碼中沒有的字段,比如在內部類中為了保持對外部類的訪問性,會自動添加指向外部類實例的字段。

    歡迎關注微信公眾號:萬貓學社,每周一分享Java技術乾貨。

    方法表集合

    方法表的結構和字段表的是一樣的,也是依次包括了訪問標誌(access_flags)、名稱索引(name_index)、描述符索引(descriptor_index)和屬性表集合(attributes)。具體如下錶:

    類型 名稱 數量 描述
    u2 access_flags 1 方法的訪問標誌
    u2 name_index 1 方法的簡單名稱索引
    u2 descriptor_index 1 方法的描述符索引
    u2 attributes_count 1 方法的屬性計數值
    attribute_info attributes attributes_count 方法的屬性

    對於方法的訪問標誌,所有標誌位和取值如下錶:

    標誌名稱 標誌值 含義
    ACC_PUBLIC 0x0001 方法是否public
    ACC_PRIVATE 0x0002 方法是否private
    ACC_PROTECTED 0x0004 方法是否protected
    ACC_STATIC 0x0008 方法是否static
    ACC_FINAL 0x0010 方法是否為final
    ACC_SYNCHRONIZED 0x0020 方法是否sychronized
    ACC_BRIDGE 0x0040 方法是否是由編譯器產生的橋接方法
    ACC_VARARGS 0x0080 方法是否接受不定參數
    ACC_NATIVE 0x0100 方法是否為native
    ACC_ABSTRACT 0x0400 方法是否為abstract
    ACC_STRICT 0x0800 方法是否為strictfp
    ACC_SYNTHETIC 0x1000 方法是否由編譯器自動產生

    方法中的Java代碼,經過編譯器編程成字節碼指令后,放在方法屬性表集合中一個名為“Code”的屬性里,後面會有更多分享。

    歡迎關注微信公眾號:萬貓學社,每周一分享Java技術乾貨。

    再來看一下之前的Class文件例子:

    方法計算值為0x0003,表示集合中有兩個方法(編譯器自動添加的無參構造方法和源碼中的plusOne方法)。第一個方法的訪問標誌是0x0001,表示只有ACC_PUBLIC標誌為true。

    名稱索引為0x0007,在常量池中為索引為7的字符串為“ ”,這就是編譯器自動添加的無參構造方法。描述符索引為0x0008,在常量池中為索引為7的字符串為“()V”,方法的屬性計數值為0x0001,表示該方法有1個屬性,屬性名稱索引為0x0009,在常量池中為索引為7的字符串為“Code”。以下是常量池相關內容:

       #7 = Utf8          <init>
       #8 = Utf8          ()V
       #9 = Utf8          Code

    歡迎關注微信公眾號:萬貓學社,每周一分享Java技術乾貨。

    屬性表集合

    屬性表(attribute_info)在前面的分享中出現了幾次,在Class文件、字段表、方法表都可以有自己的屬性表集合,用來描述某些場景下特有的信息。

    屬性表不在要求具有嚴格的順序,並且只要不與已有的屬性名重複,任何人實現的編譯器都可以寫入自己定義的屬性信息,Java虛擬機在運行時會忽略掉它不認識的屬性。

    我總結了一些比較常見的屬性,如下錶:

    屬性名稱 使用位置 含義
    Code 方法表 Java代碼編譯成的字節碼指令
    ConstantValue 字段表 final關鍵字定義的常量值
    Exceptions 方法表 方法拋出的異常
    InnerClasses 類文件 內部類列表
    LineNumberTable Code屬性 Java源碼的行號與字節碼指定的對應關係
    LocalVariableTable Code屬性 方法的局部變量描述
    SourceFile 類文件 記錄源文件名稱

    對於每個屬性,它的名稱都從常量池中引用一個CONSTANT_Utf8_info類型的常量,而屬性值的結構則是完全自定義的,只需要用一個u4類型來說明屬性值所佔的位數就可以了。具體結構如下:

    類型 名稱 數量 含義
    u2 attribute_name_index 1 屬性名稱索引
    u2 attribute_length 1 屬性值所佔的位數
    u1 info attribute_length 屬性值

    歡迎關注微信公眾號:萬貓學社,每周一分享Java技術乾貨。

    總結

    Class文件主要由魔數、次版本號、主版本號、常量池集合、訪問標誌、類索引、父類索引、接口索引集合、字段表集合、方法表集合和屬性表集合組成。隨着JDK版本的不斷升級,Class文件結構也在不斷更新,學習之路,永不止步。

    歡迎關注微信公眾號:萬貓學社,每周一分享Java技術乾貨。

    本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理【其他文章推薦】

    收購3c,收購IPHONE,收購蘋果電腦-詳細收購流程一覽表

    網頁設計公司推薦更多不同的設計風格,搶佔消費者視覺第一線

    ※廣告預算用在刀口上,網站設計公司幫您達到更多曝光效益

    ※公開收購3c價格,不怕被賤賣!

    ※自行創業 缺乏曝光? 下一步"網站設計"幫您第一時間規劃公司的門面形象

  • 油電風潮吹進賽車界,美國印地賽車 2022 年引進混合動力

    油電風潮吹進賽車界,美國印地賽車 2022 年引進混合動力

    近年來電動車和油電混合車越來越受到矚目,就連強調性能和速度的賽車都迎上這股浪潮,美國知名的印地賽車系列賽(IndyCar)就宣布將引進油電混合動力。

    印地賽車系列賽宣布將在 2022 年賽季導入油電混合動力,堪稱是一項重大的變革。印地賽車和本田(Honda)和雪佛蘭(Chevrolet)合作,混合動力系統也將由兩大車廠供應的引擎為基礎。導入混合動力系統的新引擎預計動力輸出可以超過 900 匹馬力,讓新的賽車有更高的動力。

    使用混合動力系統也代表賽車將從傳統以手持式電動啟動器來發動引擎的方式,轉變為可以由賽車手從駕駛艙直接啟動。從安全角度來看,這讓車手在停下來時能自行重新啟動賽車,無需等待從外部手動啟動,有助於減少工作人員在賽道上的時間,降低車手和工作人員的風險。賽車引進混合動力系統可以增加推進系統的馬力,相對也就順帶加快了比賽的節奏,減少整體賽事需要的時間。

    2022.

    The next era:

    — NTT IndyCar Series (@IndyCar)

    「隨著汽車的發展和像是引擎整合混合動力系統這類的創新,對印地賽車系列賽而言是一個讓人興奮的時刻」,印地賽車系列賽的主席 Jay Frye 表示。預計 2022 年會開始導入混合動力系統,並配合引進新一代的車架的時間,也讓其他供應商有機會加入本田和雪佛蘭的行列。新的引擎規則預計會從 2022 年實施到 2027 年賽季,共維持 6 年的時間,確保引擎製造商和賽車團隊能有明確和穩定的規範。

    消息公布之後,不少車手都樂觀看待混合動力系統的加入,2017 年年度冠軍 Josef Newgarden 也在 Twitter 上表示喜歡這項變革,並且對 900 匹以上的馬力感到興奮。油電混合動力的賽車能開始在賽場上競技,或許也是新技術逐漸受到各界接受的重要訊號之一。

    900+ HP!!!! Let’s goooooo!!!

    Love the direction is going! Who’s excited for 2022?!

    — Josef Newgarden (@josefnewgarden)

    (合作媒體:。首圖來源: CC BY 2.0)

    本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

    【其他文章推薦】

    3c收購,鏡頭 收購有可能以全新價回收嗎?

    台北網頁設計公司這麼多,該如何挑選?? 網頁設計報價省錢懶人包"嚨底家"

    網頁設計公司推薦更多不同的設計風格,搶佔消費者視覺第一線

    ※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

    賣IPHONE,iPhone回收,舊換新!教你怎麼賣才划算?

  • OpenJS基金會推出Node.js證書,JS開發者可以“考證”了

    OpenJS基金會推出Node.js證書,JS開發者可以“考證”了

      OpenJS 基金會近日在其官方博客公布了最新啟動的專業認證計劃。據介紹,此項認證計劃重點關注 Node.js 開發者在專業環境中構建 Node.js 應用和服務所需的關鍵技能。

      開發者通過認證后,可獲得由 OpenJS 基金會頒發和認證的證書,證書有效期為三年,其中包括 PDF 證書和数字徽章,到期后可重新認證。

      正如上面提到的,此項認證主要是考查開發者構建 Node.js 應用和服務所需的關鍵技能,所以 OpenJS 基金會也推出了兩個證書來對這兩種技能進行認證,這兩個證書分別為 OpenJS Node.js 應用開發者證書和 OpenJS Node.js 服務開發者證書。

      據官方介紹,OpenJS Node.js 應用開發者 (JSNAD) 證書非常適合具有至少兩年 Node.js 使用經驗的開發者,有關報名或其他更多信息請點擊這裏進行了解。OpenJS Node.js 服務開發者 (JSNSD) 證書則更適合具有使用 Node.js 創建 RESTful 服務器以及服務的經驗。詳情請點此了解。

      另外,兩項考試的時長都為兩個小時,開發者通過基於瀏覽器的終端進行考試,如果有需要,每項考試都支持自動免費重考。考試現場會有監督員進行監督,並以英文的方式在線進行。

      OpenJS 基金會執行董事 Robin Ginn 表示:“ OpenJS Node.js 專業認證計劃旨在幫助開發者展示其在現實環境中的 Node.js 水平,併為他們提供將這些技術引入各自組織的知識。認證考試不僅僅是一種與供應商無關的考查方式,它還提供了一個由 Node.js 社區的專業從業者開發的框架,此框架還為經驗豐富的開發者闡述清楚關於 Node.js 的各種技能。”

      關於 OpenJS 基金會 

      OpenJS 基金會的使命是通過提供一个中立的組織來託管項目並協作資助有益於整個生態系統的活動,從而促進 JavaScript 和 Web 生態系統的健康發展。

      OpenJS 基金會由 32 個開源 JavaScript 項目組成,其中包括 Appium,Dojo,jQuery,Node.js 和 Webpack,並得到 30 個企業和最終用戶成員的支持,其中包括 GoDaddy,Google,IBM,Intel,Joyent 和 Microsoft。

      這些成員清楚地認識到 JavaScript 生態系統所具備的相互聯繫的性質,以及為代表重要共享價值的項目提供中心位置的重要性。 

     

    本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理【其他文章推薦】

    收購3c,收購IPHONE,收購蘋果電腦-詳細收購流程一覽表

    網頁設計公司推薦更多不同的設計風格,搶佔消費者視覺第一線

    ※廣告預算用在刀口上,網站設計公司幫您達到更多曝光效益

    ※公開收購3c價格,不怕被賤賣!

    ※自行創業 缺乏曝光? 下一步"網站設計"幫您第一時間規劃公司的門面形象

  • 長慶油田發現10億噸級大油田

      科技日報訊 (杜英)“長慶油田在甘肅慶陽勘探發現了儲量 10 億噸級的慶城大油田,慶城油田目前已建成百萬噸級生產能力。”10 月 25 日,中國石油天然氣股份有限公司長慶油田分公司對外發布了這一消息。

      資料显示,2018 年全國生產原油是 1.89 億噸,而慶城大油田新增地質儲量合計達 10.51 億噸。“我國原油對外依存度 2018 年已突破 70%,儲量規模 10 億噸級慶城油田的發現,在未來3—4 年內將建成 300 萬噸的生產能力,相當於又給國家建成一个中型油田。”長慶油田公司新聞發言人李逵表示,新油田的發現對支撐長慶油田保障國家油氣安全戰略將發揮重要作用。

      “此次勘探獲得重大突破,得益於長慶油田對鄂爾多斯盆地石油勘探地質理論和三維地震、成像測井技術不斷創新,更源於水平井優快鑽井、水力加砂壓裂核心技術的突破。”長慶油田分公司副總經理付金華說。自 2011 年始,長慶油田開展了近十年的非常規石油勘探地質理論創新、工藝核心配套技術攻關及水平井試驗區建設。近兩年來,通過持續加強儲層緻密機理與成藏機理和富集規律等關鍵科技問題攻關,明確了長 7 源內油藏形成機理受控於穩定構造背景;建立了長 7 油藏“四控”富集模式;形成了對長 7 石油資源宏觀、立體、全方位的新認識,形成了長 7 油藏規模勘探、效益開發的地質理論,“十年磨一劍,長慶油田終於打開了非常規資源的寶庫。”付金華表示。

    本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理【其他文章推薦】

    3c收購,鏡頭 收購有可能以全新價回收嗎?

    台北網頁設計公司這麼多,該如何挑選?? 網頁設計報價省錢懶人包"嚨底家"

    網頁設計公司推薦更多不同的設計風格,搶佔消費者視覺第一線

    ※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

    賣IPHONE,iPhone回收,舊換新!教你怎麼賣才划算?