主頁 > 後端開發 > 【java8新特性】02:常見的函式式介面

【java8新特性】02:常見的函式式介面

2022-09-19 07:15:14 後端開發

Jdk8提供的函式式介面都在java.util.function包下,Jdk8的函式式型別的介面都有@FunctionInterface注解所標注,但實際上即使沒有該注解標注的有且只有一個抽象方法的介面,都可以算是函式式介面,
在JDK8中內置的四大核心函式式介面如下:

函式式介面介面型別引數型別回傳型別作用Stream流中的應用場景
Consumer<T> 消費型介面 T void 對型別為T的物件進行操作,包含方法為accpet(T t) 如forEach、peek等方法的函式式介面都是Consumer型別
Supplier<T> 供給型介面 T 回傳型別為T的物件,包含方法為T get() 如collect等方法的某些方法多載就是用的Supplier型別
Function<T,R> 函式型介面 T R 對型別為T的物件進行操作,回傳結果為 R型別的物件,包含方法為R apply(T t) 如map,flatMap等方法的函式式介面都是Function型別
Predicate<T> 斷言型介面 T boolean 確定型別為T的物件是否滿足約束,并回傳約束結果,包含方法為boolean test(T t) 如filter等方法的函式式介面都是Predicate型別

Consumer<T>

Consumer<T>消費型介面,顧名思義就是消費并處理引數,且不反饋呼叫環境

基本使用

public class Main {
    /**
     * Consumer<T>
     *     消費型介面:顧名思義主要用于消費引數,不反饋呼叫環境(沒有回傳值)
     *     accept: 抽象方法實作,用于呼叫方法,
     *     andThen: 默認實作方法,內部允許我們鏈式呼叫
     */
    public static void main(String[] args) {
        // 給定字串轉為大寫并輸出到控制臺,匿名內部類的方式實作
        Consumer<String> con1 = new Consumer<String>() {
            @Override
            public void accept(String str) {
                System.out.println("通過匿名內部類的方式:"+ str.toUpperCase());
            }
        };
        // 執行該方法的時候,我們傳入了給定引數字串,它會去執行我們上述實作的accept方法并傳入引數,最后執行我們給定的代碼邏輯
        con1.accept("abc");
        // 給定字串轉為大寫并輸出到控制臺,通過Lambda運算式實作
        Consumer<String> con2 = (text)-> System.out.println("通過Lambda運算式的方式:"+ text.toUpperCase());
        con2.accept("goods");
        /**
         * 最終結果:
         * 通過匿名內部類的方式:ABC
         * 通過Lambda運算式的方式:GOOD
         * 使用lambda運算式,我們只需要記住引數串列和執行邏輯即可,其他的我們無需關注,
         */
    }}

學習案例

public class Main {

    /**
     * Consumer<T>
     *     消費型介面:顧名思義主要用于消費引數,不反饋呼叫環境(沒有回傳值)
     *     accept: 抽象方法實作,用于呼叫方法,
     *     andThen: 默認實作方法,內部允許我們鏈式呼叫
     */
    public static void main(String[] args) {
        // 1.我們需要將集合進行排序后在輸出到控制臺
        Consumer<List> con1 = list-> {
            System.out.println("排序前的集合:"+ list);
            Collections.sort(list);
            System.out.println("排序后的集合:"+list);
        };
        con1.accept(Arrays.asList(1,5,3,2,9,6,7));
        /**
         * 最終結果:
         * 排序前的集合:[1, 5, 3, 2, 9, 6, 7]
         * 排序后的集合:[1, 2, 3, 5, 6, 7, 9]
         */
        // 上面執行邏輯實作分兩步,第一步需要獲取到給定集合進行排序,第二個則是輸出排序后的集合
        // 如果以上兩個步驟分別用兩個consumer也可以實作,我們可以定義一個方法接收兩個consumer進行操作
        accept(Arrays.asList(1,5,3,2,9,6,7),list->
        {
            System.out.println("andThen鏈式呼叫前集合:"+list);
            Collections.sort(list);
        },list-> System.out.println("andThen鏈式呼叫后集合:"+ list));
        /**
         * 最終結果:
         * andThen鏈式呼叫前集合:[1, 5, 3, 2, 9, 6, 7]
         * andThen鏈式呼叫后集合:[1, 2, 3, 5, 6, 7, 9]
         */
        // 如果consumer引數多個的話,我們可以直接在Lambda運算式進行鏈式呼叫,不費那勁定義方法了
        Consumer<List> con2 = ((Consumer<List>) list -> {
            System.out.println("lambda運算式的鏈式呼叫前集合:" + list);
            Collections.sort(list);
        }).andThen(list -> System.out.println("lambda運算式的鏈式呼叫后集合:"+list));
        // 需要注意的是:要使用這種方式,第一個consumer要進行鏈式呼叫必須要強行指定為(Consumer)型別,后續的介面才能夠呼叫方法
        con2.accept(Arrays.asList(1,53,31,25,99,62,17));
        /**
         * 最終結果:
         * lambda運算式的鏈式呼叫前集合:[1, 53, 31, 25, 99, 62, 17]
         * lambda運算式的鏈式呼叫后集合:[1, 17, 25, 31, 53, 62, 99]
         */
    }

    public static void accept(List<Integer> list,Consumer<List> con1,Consumer<List> con2){
        // 鏈式呼叫時會優先執行左邊的介面實作,依次往右執行 我們的需求是先排序后輸出,第一個Consumer是排序,第二個是輸出,
        con1.andThen(con2).accept(list);
    }
}

總結

1.函式式介面的本質實際上就是將函式以引數的形式進行傳遞

2.Consumer是消費型的函式式介面,通常用于資料內部處理,沒有回傳值

3.除了Consumer之外,還有各種消費型的函式式介面,還有IntConsumer、LongConsumer等、如果需要傳遞兩個引數則可以使用BIFunction、也可以根據自身需求進行自定義,

Supplier<T>

Consumer<T>供給型函式式介面,顧名思義就是供給資料給呼叫環境,不接收引數傳遞

基本使用

public class Main{
    /**
     * 供給型函式式介面顧名思義就是顧名思義就是供給資料給呼叫環境,不接收引數傳遞
     *  T get() : 回傳泛型T型別的引數到呼叫環境
     */
    public static void main(String[] args) {
        // 回傳一個0-100間的亂數
        Supplier<Integer> sup1 = new Supplier<Integer>() {
            @Override
            public Integer get() {
                int res = new Random().nextInt(100);
                System.out.println("通過匿名內部類的方式獲取到的亂數:"+ res);
                return res;
            }
        };
        // 執行該方法的時候,它會去執行我們上述實作的get方法,
        sup1.get();
        // 通過lambda運算式的方式進行實作
        Supplier<Integer> sup2 = ()-> {
            int res = new Random().nextInt(100);
            System.out.println("通過lambda運算式的方式獲取到的亂數:"+ res);
            return res;};
        sup2.get();
        /**
         * 最終結果:
         * 通過匿名內部類的方式獲取到的亂數:28
         * 通過lambda運算式的方式獲取到的亂數:62
         * 使用lambda運算式,我們只需要記住引數串列和執行邏輯即可,其他的我們無需關注,
         */
    }
}

 學習案例

public class Main{

    public static Map<String,String> redis = new HashMap();
    
    /**
     * 供給型函式式介面顧名思義就是顧名思義就是供給資料給呼叫環境,不接收引數傳遞
     *  T get() : 回傳泛型T型別的引數到呼叫環境
     */
    public static void main(String[] args) {
        // 1.(模擬)查詢某個Key在redis中有沒有快取,快取沒有則從資料庫取完存入redis再回傳,有的話則直接回傳
        String val = getCache("title");
        String val2 = getCache("title");
        String val3 = getCache("title");
        /**
         * 最終結果:
          從資料庫中獲取:我是標題
          從快取中獲取:我是標題
          從快取中獲取:我是標題
         */
        // 可以看到經過第一次后續都是直接從快取中取出的資料
    }

    public static String getCache(String key){
        String val = redis.get(key);
        if(Objects.isNull(val)){
            // 獲取資料庫的資料
            val = getDbVal(() -> "我是標題");
            System.out.println("從資料庫中獲取:"+val);
            redis.put(key,val);
            return val;
        }
        System.out.println("從快取中獲取:"+val);
        return val;
    }

    public static String getDbVal(Supplier<String> supplier){
       return  supplier.get();
    }
}

總結

1.函式式介面的本質實際上就是將函式以引數的形式進行傳遞

2.Supplier是供給型的函式式介面,通常用于構建某個物件處理后回傳呼叫環境

3.除了Supplier之外,還有各種供給型的函式式介面,還有BooleanSupplier、IntSupplier等,

Function<T,R>

 Function<T,R>函式型的函式式介面,泛型T是引數、泛型R則是回傳值、主要應用場景做資料型別轉換等,

基本使用

public class Main{

    /**
     *  Function<T,R>函式型的函式式介面,泛型T是引數、泛型R則是回傳值、主要應用場景做資料型別轉換等,
     *  R apply(T t): 抽象方法實作,用于呼叫方法并回傳泛型R
     *  <V> Function<T, V> andThen: 默認實作方法,內部允許我們鏈式呼叫,與其他的andThen原理一致,
     *  <V> Function<V, R> compose: 默認實作方法,內部允許我們鏈式呼叫,呼叫方式與andThen一樣,但執行順序不一樣,compose是先執行compose中的函式介面,再執行左邊呼叫的函式介面,依次往左
     *  <T> Function<T, T> identity():回傳當前執行的方法,從原始碼中我們也可以看到它回傳的是當前的t
     */
    public static void main(String[] args) {

        // 傳入給定字串,回傳轉換后的Integer型別
        Function<String,Integer> fun1 = new Function<String, Integer>() {
            @Override
            public Integer apply(String s) {
                Integer convert = Integer.valueOf(s);
                System.out.println("通過匿名內部類的方式獲取到的值:"+ convert +",資料型別是否為Integer?結果:" + (convert instanceof Integer));
                return convert;
            }
        };
        // 執行該方法的時候,它會去執行我們上述實作的apply方法,
        fun1.apply("10086");
        // 通過lambda運算式的方式進行實作
        Function<String,Integer> fun2 = s->{
            Integer convert = Integer.valueOf(s);
            System.out.println("通過lambda運算式的方式獲取到的值:"+ convert +",資料型別是否為Integer?結果:" + (convert instanceof Integer));
            return convert;
        };
        fun2.apply("10000");
        /**
         * 通過匿名內部類的方式獲取到的值:10086,資料型別是否為Integer?結果:true
         * 通過lambda運算式的方式獲取到的值:10000,資料型別是否為Integer?結果:true
         * 使用lambda運算式,我們只需要記住引數串列和執行邏輯即可,其他的我們無需關注,
         */
        // 我們繼續對Function的API做一些理解和補充,畢竟這玩意在作業中經常會用上
        // andThen 我們都知道常用于鏈式呼叫的,這里必須保證T和V型別是一樣的,也就是引數泛型T和回傳值泛型V
        Function<String,String> fun3 = x-> {
            System.out.println("我是fun3的方法");
            return x;
        };
        Function<String,String> fun4 = y-> {
            System.out.println("我是fun4的方法");
            return y;
        };
        fun3.andThen(fun4).apply("test");
        /**
         * 最終結果:
         * 我是fun3的方法
         * 我是fun4的方法
         */
        // 我們發現這里是先執行fun3的apply方法再執行fun4的apply方法的,
        // compose 與andThen一樣都是鏈式呼叫,但結果卻大大不同,這里必須保證T和V型別是一樣的,也就是引數泛型T和回傳值泛型V
        fun3.compose(fun4).apply("test");
        /**
         * 最終結果:
         * 我是fun4的方法
         * 我是fun3的方法
         */
        // 我們發現這里是先執行的fun4的apply方法再執行fun3的apply方法的
        // 由此我們推斷出compose和andThen的區別就在于,compose介面方法執行順序從右到左,而andThen則是從左到右,
        Function<Object, Object> identity = Function.identity();
        // Function.identity() 靜態方法這里就不好演示了,這個通常在后面搭配Stream流轉Map型別的時候用到,它回傳本身
    }
}

學習案例

public class Main{

    /**
     *  Function<T,R>函式型的函式式介面,泛型T是引數、泛型R則是回傳值、主要應用場景做資料型別轉換等,
     *  R apply(T t): 抽象方法實作,用于呼叫方法并回傳泛型R
     *  <V> Function<T, V> andThen: 默認實作方法,內部允許我們鏈式呼叫,與其他的andThen原理一致,
     *  <V> Function<V, R> compose: 默認實作方法,內部允許我們鏈式呼叫,呼叫方式與andThen一樣,但執行順序不一樣,compose是先執行compose中的函式介面,再執行左邊呼叫的函式介面,依次往左
     *  <T> Function<T, T> identity():回傳當前執行的方法,從原始碼中我們也可以看到它回傳的是當前的t
     */
    public static void main(String[] args) {
        List<Person> persons = Arrays.asList(new Person(1,"張三"),new Person(2,"李四"));
        // 給定一個person物件集、轉換成姓名屬性集合回傳
        Function<List<Person>,List<String>> fun1 = list-> {
            List<String> arr = new ArrayList<>();
            for (int i = 0;  i < list.size(); i++) {
                arr.add(list.get(i).getName());
            }
            return arr;
        };
        List<String> personNames = fun1.apply(persons);
        System.out.println(personNames);
        /**
         * 最終結果:
         * 結果:[張三, 李四]
         */
    }
}

class Person{
    private Integer id;
    private String name;

    public Person(Integer id, String name) {
        this.id = id;
        this.name = name;
    }


    public void setId(Integer id) {
        this.id = id;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getId() {
        return id;
    }

    public String getName() {
        return name;
    }
}

總結

1.函式式介面的本質實際上就是將函式以引數的形式進行傳遞

2.Function是函式型的函式式介面,通常用于構建某個物件處理后回傳呼叫環境

3.除了Function之外,還有各種函式型的函式式介面,還有BIFunction、ToIntFunction等,

Predicate

 Predicate<T> 斷言型的函式式介面,泛型T是引數、回傳結果型別為布爾型別的函式介面,

基本使用

public class Main{

    /**
     *  Predicate<T>斷言型的函式式介面,泛型T是引數、回傳結果型別為布爾型別的函式介面,
     *  boolean test(T t): 抽象方法實作,用于回傳傳入的引數邏輯運算后布爾型別結果
     *  Predicate<T> and: 默認實作方法,內部允許我們鏈式呼叫,用于同時判定多個Predicate函式介面的實作 類似于邏輯運算中的短路&操作,
     *  Predicate<T> negate: 默認實作方法,內部允許我們鏈式呼叫,用于同時判定多個Predicate函式介面的實作,用于將當前判定結果取反后回傳,類似于邏輯運算中的!操作
     *  Predicate<T> or:默認實作方法,內部允許我們鏈式呼叫,用于同時判定多個Predicate函式介面的實作 類似于邏輯運算中的||操作,
     *  Predicate<T> isEqual:靜態方法,內部允許我們鏈式呼叫,在保證引數不是空的情況下它內部實作邏輯實際上呼叫的是Object的equals,具體equals看子類有沒有重寫
     */
    public static void main(String[] args) {
        Predicate<String> pre1 = new Predicate<String>() {
            @Override
            public boolean test(String o) {
                boolean bool = o.matches("[0-9]{1,}");
                System.out.println("通過匿名內部類的方式獲取到的值:"+ bool);
                return bool;
            }
        };
        // 執行該方法的時候,它會去執行我們上述實作的test方法,
        pre1.test("10086");
        Predicate<String> pre2 = text->{
            boolean bool = text.matches("[0-9]{1,}");
            System.out.println("通過lambda運算式的方式獲取到的值:"+ bool);
            return bool;
        };
        pre2.test("10086a");
        /**
         * 最終結果:
         * 通過匿名內部類的方式獲取到的值:true
         * 通過lambda運算式的方式獲取到的值:false
         * 使用lambda運算式,我們只需要記住引數串列和執行邏輯即可,其他的我們無需關注,
         */
        // 我們繼續對Predicate的API做一些理解和補充,畢竟這玩意在作業中經常會用上
        // and 實際上等價于邏輯運算子中的短路&操作
        Predicate<String> fun3 = x->
        {
            System.out.println("先計算fun3");
            return true;
        };
        Predicate<String> fun4 = x->
        {
            System.out.println("先計算fun4");
            return false;
        };
        System.out.println("第一次and結果:"+fun3.and(fun4).test("test"));
        /**
         * 最終結果:
         * 先計算fun3
         * 先計算fun4
         * 本次結果:false
         */
        // 那么為什么我們知道它是短路&的操作 而不是&的操作呢?,我們只需要將第一個函式式介面回傳false,看看它還會不會執行第二個函式式介面即可
        Predicate<String> fun5 = x->
        {
            System.out.println("先計算fun5");
            return false;
        };
        Predicate<String> fun6 = x->
        {
            System.out.println("先計算fun6");
            return true;
        };
        System.out.println("第二次and結果:"+fun5.and(fun6).test("test"));
        /**
         * 最終結果:
         * 先計算fun5
         * 第二次and結果:false,
         */
        // 從結果我們其實可以推斷出,在第一個結果為true的情況下第二個fun6壓根沒進,所以是短路&
        // 并且起始在and方法原始碼中給我們也可以看到 return (t) -> test(t) && other.test(t); 是短路&

        // negate 實際上等價于邏輯運算子中的!操作
        // 我們直接取上面的值做例子,本來結果應該為false,取反后應該為true
        System.out.println("negate結果:"+fun5.and(fun6).negate().test("test"));
        /**
         * 最終結果:
         * negate結果:true
         */

        // or 等價于邏輯運算子中的||操作
        // 我們直接取上面的做例子,第一個為false,第二個為true、||的最終結果應該為true
        System.out.println("or結果:"+fun5.or(fun6).test("test"));
        /**
         * 最終結果:
         * or結果:true
         */

        // isEqual 內部呼叫的是Object的equals方法,如果子類重寫了equals則調起子類的equals方法
        // 如我們常用的String就重寫了Object的equals方法,我們以它做例子
        Predicate<String> fun7 = Predicate.isEqual("Hello");
        System.out.println("isEquals第一次結果:"+ fun7.test("Hello"));
        /**
         * 最終結果:
         * isEquals第一次結果:true
         */
        Predicate<String> fun8 = Predicate.isEqual("World");
        System.out.println("isEquals第二次結果:"+ fun8.test("Hello"));
        // 自定義的物件型別也是可以比較的,但需要重寫equals和hashCode,這里就不寫示例了,可以自己玩玩

        // 以上就是Predicate的相關API的介紹
    }
}

學習案例

public class Main{

    /**
     *  Predicate<T>斷言型的函式式介面,泛型T是引數、回傳結果型別為布爾型別的函式介面,
     *  boolean test(T t): 抽象方法實作,用于回傳傳入的引數邏輯運算后布爾型別結果
     *  Predicate<T> and: 默認實作方法,內部允許我們鏈式呼叫,用于同時判定多個Predicate函式介面的實作 類似于邏輯運算中的短路&操作,
     *  Predicate<T> negate: 默認實作方法,內部允許我們鏈式呼叫,用于同時判定多個Predicate函式介面的實作,用于將當前判定結果取反后回傳,類似于邏輯運算中的!操作
     *  Predicate<T> or:默認實作方法,內部允許我們鏈式呼叫,用于同時判定多個Predicate函式介面的實作 類似于邏輯運算中的||操作,
     *  Predicate<T> isEqual:靜態方法,內部允許我們鏈式呼叫,在保證引數不是空的情況下它內部實作邏輯實際上呼叫的是Object的equals,具體equals看子類有沒有重寫
     */
    public static void main(String[] args) {
        // 判斷給定字串是否純數字并且小于10 可以使用and進行鏈式呼叫
        Predicate<String> pre1 = ((Predicate<String>) s -> s.matches("[0-9]{1,}")).and(x->Integer.valueOf(x) <10);
        System.out.println("使用and方式進行鏈式呼叫:"+pre1.test("9"));
        // 需要注意的是:要使用這種方式,第一個Predicate要進行鏈式呼叫必須要強行再指定為(Predicate)型別,后續的介面才能夠呼叫方法
        // 實際上這種方式用的比較少,因為比較麻煩,所以一般都會直接使用&&進行判定
        Predicate<String> pre2 = s->  s.matches("[0-9]{1,}") && Integer.valueOf(s) <10;
        System.out.println("使用&&方式呼叫:"+pre2.test("10"));
        /**
         * 最終結果:
         * 使用and方式進行鏈式呼叫:true
         * 使用&&方式呼叫:false
         */
    }
}

以上就是Jdk8提供的基礎的四大函式(除了這四個大的分類還有許多函式式介面,也可以自定義函式式介面實作我們的需求)的基本使用方式和一些簡單案例,具體該怎么做怎么寫則需要根據專案實際需求進行,通常函式式介面都會搭配Stream成套使用,目前也有很多框架支持函式式介面的方式、如MyBatis-plus等社區活躍度較高的框架,

 

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/508989.html

標籤:Java

上一篇:總結一下今天所學的知識9.18

下一篇:微信小程式--云開發

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【C++】Microsoft C++、C 和匯編程式檔案

    ......

    uj5u.com 2020-09-10 00:57:23 more
  • 例外宣告

    相比于斷言適用于排除邏輯上不可能存在的狀態,例外通常是用于邏輯上可能發生的錯誤。 例外宣告 Item 1:當函式不可能拋出例外或不能接受拋出例外時,使用noexcept 理由 如果不打算拋出例外的話,程式就會認為無法處理這種錯誤,并且應當盡早終止,如此可以有效地阻止例外的傳播與擴散。 示例 //不可 ......

    uj5u.com 2020-09-10 00:57:27 more
  • Codeforces 1400E Clear the Multiset(貪心 + 分治)

    鏈接:https://codeforces.com/problemset/problem/1400/E 來源:Codeforces 思路:給你一個陣列,現在你可以進行兩種操作,操作1:將一段沒有 0 的區間進行減一的操作,操作2:將 i 位置上的元素歸零。最終問:將這個陣列的全部元素歸零后操作的最少 ......

    uj5u.com 2020-09-10 00:57:30 more
  • UVA11610 【Reverse Prime】

    本人看到此題沒有翻譯,就附帶了一個自己的翻譯版本 思考 這一題,它的第一個要求是找出所有 $7$ 位反向質數及其質因數的個數。 我們應該需要質數篩篩選1~$10^{7}$的所有數,這里就不慢慢介紹了。但是,重讀題,我們突然發現反向質數都是 $7$ 位,而將它反過來后的數字卻是 $6$ 位數,這就說明 ......

    uj5u.com 2020-09-10 00:57:36 more
  • 統計區間素數數量

    1 #pragma GCC optimize(2) 2 #include <bits/stdc++.h> 3 using namespace std; 4 bool isprime[1000000010]; 5 vector<int> prime; 6 inline int getlist(int ......

    uj5u.com 2020-09-10 00:57:47 more
  • C/C++編程筆記:C++中的 const 變數詳解,教你正確認識const用法

    1、C中的const 1、區域const變數存放在堆疊區中,會分配記憶體(也就是說可以通過地址間接修改變數的值)。測驗代碼如下: 運行結果: 2、全域const變數存放在只讀資料段(不能通過地址修改,會發生寫入錯誤), 默認為外部聯編,可以給其他源檔案使用(需要用extern關鍵字修飾) 運行結果: ......

    uj5u.com 2020-09-10 00:58:04 more
  • 【C++犯錯記錄】VS2019 MFC添加資源不懂如何修改資源宏ID

    1. 首先在資源視圖中,添加資源 2. 點擊新添加的資源,復制自動生成的ID 3. 在解決方案資源管理器中找到Resource.h檔案,編輯,使用整個專案搜索和替換的方式快速替換 宏宣告 4. Ctrl+Shift+F 全域搜索,點擊查找全部,然后逐個替換 5. 為什么使用搜索替換而不使用屬性視窗直 ......

    uj5u.com 2020-09-10 00:59:11 more
  • 【C++犯錯記錄】VS2019 MFC不懂的批量添加資源

    1. 打開資源頭檔案Resource.h,在其中預先定義好宏 ID(不清楚其實ID值應該設定多少,可以先新建一個相同的資源項,再在這個資源的ID值的基礎上遞增即可) 2. 在資源視圖中選中專案資源,按F7編輯資源檔案,按 ID 型別 相對路徑的形式添加 資源。(別忘了先把檔案拷貝到專案中的res檔案 ......

    uj5u.com 2020-09-10 01:00:19 more
  • C/C++編程筆記:關于C++的參考型別,專供新手入門使用

    今天要講的是C++中我最喜歡的一個用法——參考,也叫別名。 參考就是給一個變數名取一個變數名,方便我們間接地使用這個變數。我們可以給一個變數創建N個參考,這N + 1個變數共享了同一塊記憶體區域。(參考型別的變數會占用記憶體空間,占用的記憶體空間的大小和指標型別的大小是相同的。雖然參考是一個物件的別名,但 ......

    uj5u.com 2020-09-10 01:00:22 more
  • 【C/C++編程筆記】從頭開始學習C ++:初學者完整指南

    眾所周知,C ++的學習曲線陡峭,但是花時間學習這種語言將為您的職業帶來奇跡,并使您與其他開發人員區分開。您會更輕松地學習新語言,形成真正的解決問題的技能,并在編程的基礎上打下堅實的基礎。 C ++將幫助您養成良好的編程習慣(即清晰一致的編碼風格,在撰寫代碼時注釋代碼,并限制類內部的可見性),并且由 ......

    uj5u.com 2020-09-10 01:00:41 more
最新发布
  • Rust中的智能指標:Box<T> Rc<T> Arc<T> Cell<T> RefCell<T> Weak

    Rust中的智能指標是什么 智能指標(smart pointers)是一類資料結構,是擁有資料所有權和額外功能的指標。是指標的進一步發展 指標(pointer)是一個包含記憶體地址的變數的通用概念。這個地址參考,或 ” 指向”(points at)一些其 他資料 。參考以 & 符號為標志并借用了他們所 ......

    uj5u.com 2023-04-20 07:24:10 more
  • Java的值傳遞和參考傳遞

    值傳遞不會改變本身,參考傳遞(如果傳遞的值需要實體化到堆里)如果發生修改了會改變本身。 1.基本資料型別都是值傳遞 package com.example.basic; public class Test { public static void main(String[] args) { int ......

    uj5u.com 2023-04-20 07:24:04 more
  • [2]SpinalHDL教程——Scala簡單入門

    第一個 Scala 程式 shell里面輸入 $ scala scala> 1 + 1 res0: Int = 2 scala> println("Hello World!") Hello World! 檔案形式 object HelloWorld { /* 這是我的第一個 Scala 程式 * 以 ......

    uj5u.com 2023-04-20 07:23:58 more
  • 理解函式指標和回呼函式

    理解 函式指標 指向函式的指標。比如: 理解函式指標的偽代碼 void (*p)(int type, char *data); // 定義一個函式指標p void func(int type, char *data); // 宣告一個函式func p = func; // 將指標p指向函式func ......

    uj5u.com 2023-04-20 07:23:52 more
  • Django筆記二十五之資料庫函式之日期函式

    本文首發于公眾號:Hunter后端 原文鏈接:Django筆記二十五之資料庫函式之日期函式 日期函式主要介紹兩個大類,Extract() 和 Trunc() Extract() 函式作用是提取日期,比如我們可以提取一個日期欄位的年份,月份,日等資料 Trunc() 的作用則是截取,比如 2022-0 ......

    uj5u.com 2023-04-20 07:23:45 more
  • 一天吃透JVM面試八股文

    什么是JVM? JVM,全稱Java Virtual Machine(Java虛擬機),是通過在實際的計算機上仿真模擬各種計算機功能來實作的。由一套位元組碼指令集、一組暫存器、一個堆疊、一個垃圾回收堆和一個存盤方法域等組成。JVM屏蔽了與作業系統平臺相關的資訊,使得Java程式只需要生成在Java虛擬機 ......

    uj5u.com 2023-04-20 07:23:31 more
  • 使用Java接入小程式訂閱訊息!

    更新完微信服務號的模板訊息之后,我又趕緊把微信小程式的訂閱訊息給實作了!之前我一直以為微信小程式也是要企業才能申請,沒想到小程式個人就能申請。 訊息推送平臺🔥推送下發【郵件】【短信】【微信服務號】【微信小程式】【企業微信】【釘釘】等訊息型別。 https://gitee.com/zhongfuch ......

    uj5u.com 2023-04-20 07:22:59 more
  • java -- 緩沖流、轉換流、序列化流

    緩沖流 緩沖流, 也叫高效流, 按照資料型別分類: 位元組緩沖流:BufferedInputStream,BufferedOutputStream 字符緩沖流:BufferedReader,BufferedWriter 緩沖流的基本原理,是在創建流物件時,會創建一個內置的默認大小的緩沖區陣列,通過緩沖 ......

    uj5u.com 2023-04-20 07:22:49 more
  • Java-SpringBoot-Range請求頭設定實作視頻分段傳輸

    老實說,人太懶了,現在基本都不喜歡寫筆記了,但是網上有關Range請求頭的文章都太水了 下面是抄的一段StackOverflow的代碼...自己大修改過的,寫的注釋挺全的,應該直接看得懂,就不解釋了 寫的不好...只是希望能給視頻網站開發的新手一點點幫助吧. 業務場景:視頻分段傳輸、視頻多段傳輸(理 ......

    uj5u.com 2023-04-20 07:22:42 more
  • Windows 10開發教程_編程入門自學教程_菜鳥教程-免費教程分享

    教程簡介 Windows 10開發入門教程 - 從簡單的步驟了解Windows 10開發,從基本到高級概念,包括簡介,UWP,第一個應用程式,商店,XAML控制元件,資料系結,XAML性能,自適應設計,自適應UI,自適應代碼,檔案管理,SQLite資料庫,應用程式到應用程式通信,應用程式本地化,應用程式 ......

    uj5u.com 2023-04-20 07:22:35 more