比亞迪Q1財報亮眼:淨利暴漲9倍

比亞迪昨(27)日晚間公佈2015年第1季財報,其營業收入為人民幣152.83億元(約新台幣762億元),較去年同期成長30.35%;歸屬於上市公司股東的淨利潤為人民幣1.21億元(約新台幣6億元),較去年同期成長910.75%;基本每股收益為人民幣0.05元(約新台幣0.25元)。   比亞迪表示,營業收入增長主要是汽車業務增加所致。同時比亞迪預估今年1至6月的淨利潤將達到人民幣4至4.8億元(約新台幣20至24億元),較去年同期的人民幣3.61億元(約新台幣18億元)成長10.90%至33.08%。   據證券時報網報導,在今年的佈局規劃方面,比亞迪將啟動「7+4」佈局,涵蓋私家車、公車在內的七個主要目標市場和四個特種車市場,並將憑藉自主品牌在SUV市場的突破性契機,將新能源汽車從轎車拓展至SUV車型,豐富比亞迪的產品類型。此外,比亞迪還將開發出集約用地的循環式立體充電機,積極尋求與協力廠商的合作,加快充電設施的普及。

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

【其他文章推薦】

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

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

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

南投搬家公司費用,距離,噸數怎麼算?達人教你簡易估價知識!

※教你寫出一流的銷售文案?

※超省錢租車方案

Java 反射簡介

本文部分內容參考博客。點擊鏈接可以查看原文。

1. 反射的概念

反射是指在運行時將類的屬性、構造函數和方法等元素動態地映射成一個個對象。通過這些對象我們可以動態地生成對象實例,調用類的方法和更改類的屬性值。

2. 使用場景

什麼情況下運用JAVA反射呢?如果編譯時根本無法預知對象和類可能屬於哪些類,程序只依靠運行時信息來發現該對象和類的真實信息,此時就必須使用反射。

使用反射可以實現下面的功能:

  • 在運行時判斷任意一個對象所屬的類
  • 在運行時構造任意一個類的對象
  • 在運行時判斷任意一個類所具有的方法和屬性
  • 在運行時調用任意一個對象的方法
  • 生成動態代理

3. 獲得Class對象的幾種方式

前面已經介紹過了,每個類被加載之後,系統就會為該類生成一個對應的Class對象,通過該Class對象就可以訪問到JVM中的這個類。在Java程序中獲得Class對象通常有如下3種方式。

  • 使用Class類的forName(String clazzName)靜態方法。該方法需要傳入字符串參數,該字符串參數的值是某個類的全限定類名(必須添加完整包名)。
  • 調用某個類的class屬性來獲取該類對應的Class對象。例如,Person.class將會返回Person類對應的Class對象。
  • 調用某個對象的getClass()方法。該方法是java.lang.Object類中的一個方法,所以所有的Java對象都可以調用該方法,該方法將會返回該對象所屬類對應的Class對象。

對於第一種方式和第二種方式都是直接根據類來取得該類的Class對象,相比之下,第二種方式有如下兩種優勢。

  • 代碼更安全。程序在編譯階段就可以檢查需要訪問的Class對象是否存在。
  • 程序性能更好。因為這種方式無須調用方法,所以性能更好。

也就是說,大部分時候我們都應該使用第二種方式來獲取指定類的Class對象。但如果我們只有一個字符串,例如“java.lang.String”,若需要獲取該字符串對應的Class對象,則只能使用第一種方式,使用Class的forName(String clazzName)方法獲取Class對象時,該方法可能拋出一個ClassNotFoundException異常。一旦獲得了某個類所對應的Class對象之後,程序就可以調用Class對象的方法來獲得該對象和該類的真實信息了。

4. Class類 API介紹

通過class類我們能夠獲取大量的信息:

  1. 獲取構造函數
  • Connstructor getConstructor(Class<?>… parameterTypes):返回此Class對象對應類的指定public構造器。
  • Constructor<?>[] getConstructors():返回此Class對象對應類的所有public構造器。
  • Constructor getDeclaredConstructor(Class<?>… parameterTypes):返回此Class對象對應類的指定構造器,與構造器的訪問權限無關。
  • Constructor<?>[] getDeclaredConstructors():返回此Class對象對應類的所有構造器,與構造器的訪問權限無關。
  1. 獲取方法
  • Method getDeclaredMethod(String name, Class<?>… parameterTypes):返回此Class對象對應類的指定方法,與方法的訪問權限無關。
  • Method[] getDeclaredMethods():返回此Class對象對應類的全部方法,與方法的訪問權限無關。
  1. 獲取屬性
  • Field getField(String name):返回此Class對象對應類的指定public Field。
  • Field[] getFields():返回此Class對象對應類的所有public Field。
  • Field getDeclaredField(String name):返回此Class對象對應類的指定Field,與Field的訪問權限無關。
  • Field[] getDeclaredFields():返回此Class對象對應類的全部Field,與Field的訪問權限無關。
  1. 獲取Class對應類上所包含的Annotation。
  • A getAnnotation(Class annotationClass):試圖獲取該Class對象對應類上指定類型的Annotation;如果該類型的註釋不存在,則返回null。
  • Annotation[] getAnnotations():返回該Class對象對應類上的所有Annotation。
  • Annotation[] getDeclaredAnnotations():返回直接修飾該Class對應類的所有Annotation。
  1. 獲取Class對象對應類包含的內部類。
  • Class<?>[] getDeclaredClasses():返回該Class對象對應類里包含的全部內部類。
    如下方法用於訪問該Class對象對應類所在的外部類。
  • Class<?> getDeclaringClass():返回該Class對象對應類所在的外部類。
    如下方法用於訪問該Class對象對應類所繼承的父類、所實現的接口等。
  • Class<?>[] getInterfaces():返回該Class對象對應類所實現的全部接口。
  1. 獲取Class對象對應類所繼承的父類
  • Class<? super T> getSuperclass():返回該Class對象對應類的超類的Class對象。
  1. 獲取Class對象對應類的修飾符、所在包、類名等基本信息。
  • int getModifiers():返回此類或接口的所有修飾符。修飾符由public、protected、private、final、static、abstract等對應的常量組成,返回的整數應使用Modifier工具類的方法來解碼,才可以獲取真實的修飾符。
  • Package getPackage():獲取此類的包。
  • String getName():以字符串形式返回此Class對象所表示的類的名稱。
  • String getSimpleName():以字符串形式返回此Class對象所表示的類的簡稱。
  1. 判斷該類是否為接口、枚舉、註釋類型等
  • boolean isAnnotation():返回此Class對象是否表示一個註釋類型(由@interface定義)。
  • boolean isAnnotationPresent(Class<? extends Annotation> annotationClass):判斷此Class對象是否使用了Annotation註釋修飾。
  • boolean isAnonymousClass():返回此Class對象是否是一個匿名類。
  • boolean isArray():返回此Class對象是否表示一個數組類。
  • boolean isEnum():返回此Class對象是否表示一個枚舉(由enum關鍵字定義)。
  • boolean isInterface():返回此Class對象是否表示一個接口(使用interface定義)。
  • boolean isInstance(Object obj):判斷obj是否是此Class對象的實例,該方法可以完全代替instanceof操作符。

上面的多個getMethod()方法和getConstructor()方法中,都需要傳入多個類型為Class<?>的參數,用於獲取指定的方法或指定的構造器。關於這個參數的作用,假設某個類內包含如下3個info方法簽名:

  • public void info()
  • public void info(String str)
  • public void info(String str , Integer num)

這3個同名方法屬於重載,它們的方法名相同,但參數列表不同。在Java語言中要確定一個方法光有方法名是不行的,例如,我們指定info方法——實際上可以是上面3個方法中的任意一個!如果需要確定一個方法,則應該由方法名和形參列表來確定,但形參名沒有任何實際意義,所以只能由形參類型來確定。例如,我們想要確定第二個info方法,則必須指定方法名為info,形參列表為String.class——因此在程序中獲取該方法使用如下代碼:

clazz.getMethod("info",String.class);

使用反射生成對象

  1. 利用構造函數生成對象
  • 使用Class對象的newInstance()方法來創建該Class對象對應類的實例,這種方式要求該Class對象的對應類有默認構造器,而執行newInstance()方法時實際上是利用默認構造器來創建該類的實例。
  • 先使用Class對象獲取指定的Constructor對象,再調用Constructor對象的newInstance()方法來創建該Class對象對應類的實例。通過這種方式可以選擇使用指定的構造器來創建實例。
Constructor c = clazz.getConstructor(String.class);
c.newInstance("xx");

調用方法

Method setProName = aClass.getDeclaredMethod("setProName",String.class);
setProName.setAccessible(true);
etProName.invoke(product,"我是一個產品");

操作屬性

Field[] declaredFields = aClass.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            System.out.println("fieldName:"+declaredField.getName()+" filedType:"+declaredField.getType());
        }
        Field proName = aClass.getDeclaredField("proName");
        proName.setAccessible(true);
        proName.set(product,"我是一個產品");
        System.out.println("修稿屬性:"+product);

操作數組

//使用反射動態地創建數組
//創建一個元素類型為String,長度為3的數組
Object arr = Array.newInstance(String.class, 3);
//依次為arr數組中index為0,1,2的元素賦值
Array.set(arr, 0, "榮耀盒子");
Array.set(arr, 1, "榮耀8手機");
Array.set(arr, 2, "華為mate9保時捷版");
Object o1= Array.get(arr, 0);
Object o2= Array.get(arr, 1);
Object o3= Array.get(arr, 2);
System.out.println(o1);
System.out.println(o2);
System.out.println(o3);

5. 使用Demo

public class ReflectDemo {
    public static void main(String[] args) throws Exception {
        Class<Product> aClass = Product.class;
        Constructor<?>[] declaredConstructors = aClass.getDeclaredConstructors();
        for (Constructor<?> declaredConstructor : declaredConstructors) {
            System.out.println(declaredConstructor.getName());
        }
        Constructor<Product> constructor = aClass.getConstructor(int.class, String.class);
        Product product = constructor.newInstance(10, "ds");
        System.out.println("創建對象:"+product);

        //獲取方法並調用
        Method setProName = aClass.getDeclaredMethod("setProName", String.class);
        setProName.setAccessible(true);
        setProName.invoke(product,"我是一個產品");
        System.out.println("調用方法:"+product);

        //獲取屬性,並設置屬性的值
        Field[] declaredFields = aClass.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            System.out.println("fieldName:"+declaredField.getName()+" filedType:"+declaredField.getType());
        }
        Field proName = aClass.getDeclaredField("proName");
        proName.setAccessible(true);
        proName.set(product,"我是一個產品");
        System.out.println("修稿屬性:"+product);

        //使用反射動態地創建數組
        //創建一個元素類型為String,長度為3的數組
        Object arr = Array.newInstance(String.class, 3);
        //依次為arr數組中index為0,1,2的元素賦值
        Array.set(arr, 0, "榮耀盒子");
        Array.set(arr, 1, "榮耀8手機");
        Array.set(arr, 2, "華為mate9保時捷版");
        Object o1= Array.get(arr, 0);
        Object o2= Array.get(arr, 1);
        Object o3= Array.get(arr, 2);
        System.out.println(o1);
        System.out.println(o2);
        System.out.println(o3);
        
        System.out.println("end...");
    }
}

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

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

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

南投搬家公司費用,距離,噸數怎麼算?達人教你簡易估價知識!

※教你寫出一流的銷售文案?

※超省錢租車方案

法國黃背心運動滿週年 萬人上街抗議

摘錄自2019年11月19日公視報導

11月17號適逢法國黃背心運動一週年,去年不滿總統馬克宏調漲油價的民眾發起抗議行動,在各大城市遍地開花,並逐漸演變成反對馬克宏政府政策的社運。直到現在,仍有部分示威者,每星期六都會固定集會,提醒政府他們怒火難平。今年再度出現幾萬人走上街頭的盛大場面。有群眾和鎮暴警察發生衝突,還有人闖進巴黎的老佛爺百貨,讓業者被迫停業一天。

抗議民眾表示,「我很高興能夠在這向馬克宏宣告:我們就在這裡,我們還在這裡,黃背心運動不死。儘管他們多方試圖摧毀黃背心,但黃背心屹立不搖,我們都是為了法國。」

近幾個月來,黃背心運動趨於和緩,但週年紀念又讓情勢再度激化,數萬人走上街頭。部分抗議人士推翻路邊車輛,點燃垃圾桶等物,還向鎮暴警察扔擲石頭,而警方也以催淚瓦斯和水柱還擊和驅散人群。

根據法國內政部的說法,法國全國各地星期六一共逮捕了264人,其中巴黎就佔了六成以上。黃背心支持者表示,目前他們考慮加入其他工會行動,參與12月5號開始反對馬克宏年金改革的無限期大罷工。

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

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

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

南投搬家公司費用,距離,噸數怎麼算?達人教你簡易估價知識!

※教你寫出一流的銷售文案?

※超省錢租車方案

自已做動畫及編寫程序搞清楚最大堆的實現原理

目錄

  • 背景
  • 概念
  • 最大堆
    • 最大堆的線性存儲
    • 動畫實現最大堆加入新元素
    • 代碼實現最大堆加入新元素
    • 動畫實現最大堆取出最大元素
    • 代碼實現最大堆取出最大元素
    • 程序測試
  • 最大堆的應用–優先隊列
  • 寫在最後

背景

  • 二叉樹是數據結構中的重點,也是難點。二叉樹比數組、棧、隊列等線性結構相比複雜度更高,想要做到心中有“樹”,需要自己動手畫圖、觀察、思考,才能領會其真諦。
  • 在上篇文章《自己動手作圖深入理解二叉樹、滿二叉樹及完全二叉樹》中,我們對完全二叉樹有了一定認識,該文將對一種特殊的完全二叉樹”最大堆”進行底層研究。

概念

堆(heap)通常是一個可以被看做一棵二叉樹的數組對象。堆總是滿足下列性質:

  • 堆總是一棵完全二叉樹。
  • 堆中某個節點的值總是不大於或不小於其父節點的值;

最大堆

  • 根節點最大的堆叫做最大堆
最大堆的線性存儲
  • 由於堆是一種特殊的完全二叉樹,可以利用數組集合形成線性存儲的數據結構。
/**
 * 最大堆的底層實現--數組集合形成線性存儲的數據結構
 *  * @author zhuhuix
 * @date 2020-06-28
 */
public class MaxHeap<E extends Comparable<E>> {

    // 存放元素的數組集合
    private ArrayList<E> list;

    MaxHeap() {
        this.list = new ArrayList<>();
    }

    // 得到左孩子索引
    private int getLeftChildIndex(int i) {
        return (2 * i + 1);
    }

    // 得到右孩子索引
    private int getRightChildIndex(int i) {
        return (2 * i + 2);
    }

    // 得到父結點索引
    private int getParentIndex(int i) {
        if (i == 0) {
            throw new IllegalArgumentException("非法索引值");
        } else {
            return ((i - 1) / 2);
        }
    }
}
動畫實現最大堆加入新元素
  • 加入到數組集合尾部的元素與父結點進行比較,通過上浮操作,保證所有子結點不能大於父結點。
代碼實現最大堆加入新元素
/**
 * 最大堆的底層實現
 *
 * @author zhuhuix
 * @date 2020-06-28
 */
public class MaxHeap<E extends Comparable<E>> {

    // 存放元素的數組集合
    private ArrayList<E> list;

    MaxHeap() {
        this.list = new ArrayList<>();
    }

    // 得到左孩子索引
    private int getLeftChildIndex(int i) {
        return (2 * i + 1);
    }

    // 得到右孩子索引
    private int getRightChildIndex(int i) {
        return (2 * i + 2);
    }

    // 得到父結點索引
    private int getParentIndex(int i) {
        if (i == 0) {
            throw new IllegalArgumentException("非法索引值");
        } else {
            return ((i - 1) / 2);
        }
    }

    // 添加元素
    public void add(E e) {
        this.list.add(e);
        /**
         * 將加入的結點與父結點進行比較:
         * 如果加入的結點大於父結點,則進行上浮
         * 直至新結點小於或等於父結點為止
         */

        // 獲取當前添加元素在數組中的索引
        int i = this.list.size() - 1;
        while (i > 0) {
            E current = this.list.get(i);
            E parent = this.list.get(getParentIndex(i));
            // 如果父結點元素大於當前加入的元素,則進行交換
            if (parent.compareTo(current) < 0) {
                // 交換新加入的結點與父結點的位置
                Collections.swap(this.list, i, getParentIndex(i));
            } else {
                break;
            }
            i = getParentIndex(i);
        }
    }
    
}
動畫實現最大堆取出最大元素
  • 獲取最大堆中的根結點,即為最大元素;並把尾部結點放置到根結點,並通過下沉操作,把子結點中的最大元素移動根結點。
代碼實現最大堆取出最大元素
/**
 * 最大堆的底層實現
 *
 * @author zhuhuix
 * @date 2020-06-28
 */
public class MaxHeap<E extends Comparable<E>> {

    // 存放元素的數組集合
    private ArrayList<E> list;

    MaxHeap() {
        this.list = new ArrayList<>();
    }

    // 得到左孩子索引
    private int getLeftChildIndex(int i) {
        return (2 * i + 1);
    }

    // 得到右孩子索引
    private int getRightChildIndex(int i) {
        return (2 * i + 2);
    }

    // 得到父結點索引
    private int getParentIndex(int i) {
        if (i == 0) {
            throw new IllegalArgumentException("非法索引值");
        } else {
            return ((i - 1) / 2);
        }
    }

    // 查找最大元素
    public E findMax() {
        if (this.list.size() == 0) {
            return null;
        }
        // 最大堆中的元素永遠在根結點
        return this.list.get(0);
    }

    // 取出最大元素
    public E getMax() {
        if (findMax() != null) {
            E e = findMax();

            /**
             * 取出最大元素后,需要把堆中第二大的元素放置在根結點:
             * 將根結點元素與最後面的元素進行交換,
             * 讓最後面的元素出現在根結點,並移除最大元素
             * 將根結點的元素與左右孩子結點比較,直至根結點的元素變成最大值
             */
            int i = 0;
            Collections.swap(this.list, i, this.list.size() - 1);
            this.list.remove(this.list.size() - 1);

            // 通過循環進行當前結點與左右孩子結點的大小比較
            while (getLeftChildIndex(i) < this.list.size() && getRightChildIndex(i) < this.list.size()) {
                int leftIndex = getLeftChildIndex(i);
                int rightIndex = getRightChildIndex(i);

                // 通過比較左右孩子的元素哪個較大,確定當前結點與哪個孩子進行交換
                int index = this.list.get(leftIndex).compareTo(this.list.get(rightIndex)) > 0 ? leftIndex : rightIndex;
                if (this.list.get(i).compareTo(this.list.get(index)) < 0) {
                    Collections.swap(this.list, i, index);
                } else {
                    // 如果當前結點都大於左右孩子,則結束比較
                    break;
                }
                i = index;
            }

            return e;
        } else {
            return null;
        }
    }
}

程序測試
/**
 * 最大堆的底層實現--測試程序
 *
 * @author zhuhuix
 * @date 2020-06-28
 */
public class MaxHeapTest {
    public static void main(String[] args) {
        MaxHeap<Integer> maxHeap = new MaxHeap<>();

        // 將10個数字加入形成最大堆
        int[] arrays = {19,29,4,2,27,0,38,15,12,31};
        for (int i = 0; i < arrays.length; i++) {
            maxHeap.add(arrays[i]);
        }

        // 依次從堆中取出最大值
        for (int i = 0; i < arrays.length; i++) {
            System.out.println("第"+(i+1)+"次取出堆目前的最大值:"+maxHeap.getMax());
        }
    }
}

最大堆的應用–優先隊列

優先隊列:出隊的和順序與入隊的順序無關,只與優先級相關;
優先隊列通常可以採用最大堆的數據結構來實現。

/**
 * 用最大堆的數據結構實現優先隊列
 * 
 * @author zhuhuix
 * @date 2020-06-28
 */
public class PriorityQueue<E extends Comparable<E>>  {
    private MaxHeap<E> mhp;
    PriorityQueue() {
        mhp=new MaxHeap<>();
    }

    // 入隊
    public void enqueue(E e) {
        mhp.add(e);
    }

    // 優選級最高的元素出隊
    public E dequeue() {
        return mhp.getMax();
    }

    // 查看優先級最高的元素
    public E getFront() {
        return mhp.findMax();
    }
}

寫在最後

  • 以上通過畫圖、動畫演示、代碼編寫對堆與最大堆的概念和底層實現方式,都作了深入分析;作為最大堆的反向結構,最小堆的實現也是一樣,讀者可參考以上動畫和代碼,動手練習。
  • 畫圖、編碼不易,請點贊、收藏、關注三連!!!

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

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

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

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

南投搬家費用,距離,噸數怎麼算?達人教你簡易估價知識!

※教你寫出一流的銷售文案?

※超省錢租車方案