Tuesday, November 3, 2015

开发的心得感悟


在开发中。。。。。。

开发就是实现自己的心中所想的一切!

但是真实的开发就是一次又一次的和Bug 打交道,不喜欢Bug,但是自己又不得不一次又一次的跌倒有爬起来!

泛型与多重继承的关系 Java getGenericSuperclass()和getActualTypeArguments()基本用法:




遇到的问题,在处理的时候 我提取了多次的 BaseActivity.  结构是这样子的
DetailQRcodeActivity  extends  BaseQRcodeActivity
BaseQRcodeActivity    extends  CaptureActivity
CaptureActivity            extends  BaseActivity<SingleControl>


private void controlInit() {
    Class<?> clazz;    clazz = mReferenceObj.getClass();    generateControl(clazz);    if (mControl == null) {
        generateControl(clazz.getSuperclass());    }
}

上面的处理方式:
1 mReferenceObj  是 DetailQRcodeActivity instance.  所以第一次调用 generateControl() 
之后 mControl == null.
2 mReferenceObj,getSuperClass()  直接父类。也就是 BaseQRcodeActivity,这个时候调用
generateControl()  因为BaseQRcodeActivity extends  CaptureActivity, 并没有泛型 的信息。也就是没有 SingleControl 类.
所以 此时  mControl  == null ,这是为什么呢? 原来是因为泛型在继承的时候 之影响到 她的直接子类的信息。也就是他只会影响到CaptureActivity,  而对于她的孙子 BaseQRcodeActivity,  自然就  心有余而力不足啦!解决方案也就出来了, 第一种方法只解决当前的问题,或者以后每次写这种多继承的时候,需要添加。 第二种方案 从根本上解决问题。 我喜欢第二种。 这是在关联的时候有解决!


So how to reslove this problem?
1  First way:
you  can follow this way

DetailQRcodeActivity  extends  BaseQRcodeActivity
BaseQRcodeActivity    extends  CaptureActivity< SingleControl >
CaptureActivity <? extends SingleControl >           extends  BaseActivity<SingleControl>

2 The second way:  you can do this way
private void controlInit() {
    Class<?> clazz;    clazz = mReferenceObj.getClass();    generateControl(clazz);    if (mControl == null) {
        generateControl(clazz.getSuperclass());    }
    if (mControl == null){
        generateControl(clazz.getSuperclass().getSuperclass());    }
}


in a world I love the second way, because 一劳永逸!


=======================================================

核心代码:
http://blog.csdn.net/hikvision_java_gyh/article/details/10182309


    private void generateControl(Class clazz) {
        //1 getGenericSuperclass() //通过反射获取当前类表示的实体(类,接口,基本类型或void)的直接父类的Type,
        //Type type = this.getClass().getGenericSuperclass();
        //是得到这个类的得到泛型父类
        Type type = clazz.getGenericSuperclass();

        //3 (type instanceof ParameterizedType)),这行代码的意思是
        // 如果没有实现ParameterizedType接口,即不支持泛型;
        if (type instanceof ParameterizedType) {
            ParameterizedType p = (ParameterizedType) type;

            //2 getActualTypeArguments()返回参数数组。
            //Type[] params = ((ParameterizedType) genType).getActualTypeArguments();这行代码的意思是,如果支持泛型,返回表示此类型实际类型参数的Type对象的数组,数组里放的都是对应类型的Class,因为可能有多个,所以是数组。
            Type[] arrayClasses = p.getActualTypeArguments();

            for (Type item : arrayClasses) {
                if (item instanceof Class) {
                    Class<T> tClass = (Class<T>) item;
                    if (tClass.equals(BaseControl.class) || (tClass.getSuperclass() != null
                            && tClass.getSuperclass().equals(BaseControl.class))) {

                        // the same  deal with!
                        messageProxy = new MessageProxy(mHandler);
                        mControl = ControlFactory.getControlInstance(tClass,
                                messageProxy);
                        mModel = new ModelMap();
                        mControl.setModel(mModel);
                        return;
                    }
                }
            }
        }
    }




=======================================================


1.Class<? super T> getSuperclass():返回本类的父类
  注意: 这里获取的 父类是直接父类奥。这里的继承只有一层的时候是可以的!

2.Type getGenericSuperclass():返回本类的父类,包含泛型参数信息

=========================================

附加 参考链接:

http://blog.csdn.net/hikvision_java_gyh/article/details/10182309

http://blog.csdn.net/u010167086/article/details/15336259


Monday, November 2, 2015

一个非常绚丽的 Mac 背景桌面

https://github.com/GeekHades/Aerial

开发的心得感悟


在开发中,我们总是会遇到这样那样的问题。很多的时候我们似乎总是在跟Bug 打交道,有的时候我们会很烦的,因为各种问题,我也是蛋疼的问题!

我们也不喜欢自己的代码乱糟糟的样子,自己看以来费劲。自己都不喜欢的东西,你觉得别人会喜欢吗?我还是喜欢自己的东西。

1 短小的类
开发的时候,类要尽量的短小精悍。有的时候,我们似乎更远在一个类里面做更多的事情,其实不符合单一职责原则开发模式,因为在一个类里做了很多的事情, 当你添加一个心得功能的时候,你可能会纠结,我是要添加一个新的类呢?还是在原先类的基础上 添加 一个状态的判断呢? 我的建议看你的功能的大小。改动的比较多的时候建议使用新的类,这样的话,后期维护的时候,你不需要判断各种情况。 单一职责原则。当你在原有类的基础上修改的时候其实也违背了 开闭原则!

2 喜欢抽象类
我们会遇到各种奇葩的产品和老板。我们根本无法看到为阿里的产品需求,更多的时候竟然在我们 就要发布包的时候让我们去修改东西。这个时候,作为我们的衣食父母的话,我们可以反驳吗?这种情况是产品经经理的过时,但是当你没有产品经理的时候,我只能说你就苦逼了!抽象出 基本公共的部分方法。当你遇到新的功能的时候,你只需要添加新的功能就可以了,没有必要 公共的方法没有必要再重复的写,只要在父类里处理就好了!

3 起个好名字
这就不说了,起名字的时候,就像是给自己的儿子起名字就可以了!

4 方法 
方法尽量的只负责一个功能,一个方法里面如果写的太多的话,就会画蛇添足,没有必要写那么多的没有必要的代码。一个方法尽量的只负责一个功能就好了,(这是不可能的,所以尽量吧。不可能所有的方法只负责一个功能!)

5 先思考在code
我们都会遇到这种情况,有的新的要求的时候,我们想都不想的就开始一顿乱写,写完之后,又要花费成倍的时间来填自己的挖出的坑。这是一个蛋疼的问题,因为我们测试花的时候是编码的好几倍。这是,如果你是Android你会发现,这阵的很浪费时间。

6 承认自己的技术坑
每个人都有自己不知道的知识点,以前的我总是自大的以为自己的技术是最牛逼的,自从来到这家公司之后,我就发现其实自己真的是坑的,loser. 我以前从来没有发现自己的缺点 是自己的指点




AOP 面向切面开发?



一,什么是AOP
AOP(Aspect Orient Programming),也就是面向切面编程。可以这样理解,面向对象编程(OOP)是从静态角度考虑程序结构,面向切面编程(AOP)是从动态角度考虑程序运行过程。
二、AOP 的作用。
常常通过 AOP 来处理一些具有横切性质的系统性服务,如事物管理、安全检查、缓存、对象池管理等,AOP 已经成为一种非常常用的解决方案。
三、AOP 的实现原理





















参考链接:


AOP  还是比较麻烦的问题:
http://www.iteye.com/topic/1116696

感悟!


参考链接:

http://www.zhihu.com/question/24863332

http://www.iteye.com/topic/1116696



华为荣耀6P 如何刷机?

华为荣耀手机刷机的时候是比较恶心的问题,因为之前我找了很多的文章都说只要下载几个工具就好了,其实并是不那么简单的,以为很简单的事情往往会发花费大量的时间呢!真的是很恶心的,因为 华为荣耀有一个 锁,所以 如果不经解锁的话,你是无法刷机的奥, 

解锁的方式如下:


1. 为什么要解锁?

华为手机一般具有系统锁,不能直接刷第三方ROM,解锁是为了能刷入第三方recovery,即刷入第三方ROM包。
2. 怎样申请解锁码?
1)首先申请解锁码,打开申请地址: http://www.emui.com/plugin.php?id=unlock,勾选“我已阅读以上条款并接受所有内容”,选择下一步,选择机型为荣耀6Plus相应版本机型。
2)查询手机S/N号查询:在手机的拨号界面输入*#*#2846579#*#*,进入ProjectMenu - 单板基本信息查询 - 其他查询,即可看到S/N号。
3)查询手机IMEI/MEID号:在手机的拨号界面输入*#06#即可显示出IMEI号(双卡手机,输入主IMEI/MEID号)。
4)查询手机识别码:在手机的拨号界面输入*#*#1357946#*#*,可以看到8位数字识别码。 5)最后填写网页验证码,点击确认即可,稍等片刻后即可看到下方显示红色字,即为你手持设备的解锁码。当然你也可以发邮件申请,不过比较麻烦。



无标.png (156.08 KB, 下载次数: 108)
下载附件 保存到相册
2015-2-5 16:01 上传





3.如何进行解锁?
首先,如果解锁过程中如果遇到手机没有自动重启,请直接忽略进行下一步即可。
本帖隐藏的内容 1) 安装驱动及adb工具,这里推荐大家使用改工具 :bbs.anzhi.com/thread-9007695-1-1.html ,非常适合新手,另外切勿忘记开启adb调试,我们下面都会用到,方法:设置-关于手机,然后连续点击版本号,5次后即可进入开发者模式,退回到上级,你会看到开发者选项,进入后开启USB调试即可(还不会的可以百度了解下具体开启过程)。

2)点击左下角WIN图标,在搜索文件处输入 cmd ,然后回车,即可弹出cmd命令窗口,输入adb devices,回车,如果看到类似下面第一张图输出结果,说明adb驱动及工具已成功搞定!如果出现类似第二张图的输出结果,请在进程管理器里结束掉其他任何手机连接类的进程。。


3) 然后输入 adb reboot-bootloader,手机将重启并进入一个白色背景的界面,这就是fastboot模式。


4)输入fastboot devices,即可类似如下的输出。


再输入 fastboot oem unlock ****************,*号为16位解锁密码,例如:fastboot oem unlock 1234567812345678,回车确认,将会看到如下输出,手机将发生重启,重新进入fastboot模式,不出意外,已经解锁成功。


5)我们可以查看下是否已经成功解锁,输入 fastboot oem get-bootinfo ,回车,将会看到如下输出结果,状态为unlocked 即为解锁成功。

6)最后输入 fastboot reboot,手机即可重启到系统。


4. 如何重新上锁?

解锁过程基本与解锁相似,再次不作赘述,注意解锁命令为 fastboot oem relock **************** ,用 fastboot oem get-bootinfo 命令查看时状态为relocked。

=================================================

我遇到的问题:用于申请解锁码的华为云账号未在本手机上登录超过14天!

华为 卧槽!


一个恶心的消息:你必须要 开一华为云服务。我用了半年的手机,并没有开启 云服务。感觉 华为真他妈的垃圾!




参考链接:
http://tieba.baidu.com/p/3678718686


Sunday, November 1, 2015

Java 集合之旅


世间上本来没有集合,(只有数组参考C语言)但有人想要,所以有了集合
有人想有可以自动扩展的数组,所以有了List
有的人想有没有重复的数组,所以有了set
有人想有自动排序的组数,所以有了TreeSet,TreeList,Tree**

而几乎有有的集合都是基于数组来实现的.
因为集合是对数组做的封装,所以,数组永远比任何一个集合要快。

但任何一个集合,比数组提供的功能要多

一:数组声明了它容纳的元素的类型,而集合不声明。这是由于集合以object形式来存储它们的元素。

二:一个数组实例具有固定的大小,不能伸缩。集合则可根据需要动态改变大小。

三:数组是一种可读/可写数据结构---没有办法创建一个只读数组。然而可以使用集合提供的ReadOnly方法,以只读方式来使用集合。该方法将返回一个集合的只读版本。

==============================================================

MAP : INFO

/**
 * An object that maps keys to values.  A map cannot contain duplicate keys;
 * each key can map to at most one value.
 *
 * <p>This interface takes the place of the <tt>Dictionary</tt> class, which
 * was a totally abstract class rather than an interface.
 *
 * <p>The <tt>Map</tt> interface provides three <i>collection views</i>, which
 * allow a map's contents to be viewed as a set of keys, collection of values,
 * or set of key-value mappings.  The <i>order</i> of a map is defined as
 * the order in which the iterators on the map's collection views return their
 * elements.  Some map implementations, like the <tt>TreeMap</tt> class, make
 * specific guarantees as to their order; others, like the <tt>HashMap</tt>
 * class, do not.
 *
 * <p>Note: great care must be exercised if mutable objects are used as map
 * keys.  The behavior of a map is not specified if the value of an object is
 * changed in a manner that affects <tt>equals</tt> comparisons while the
 * object is a key in the map.  A special case of this prohibition is that it
 * is not permissible for a map to contain itself as a key.  While it is
 * permissible for a map to contain itself as a value, extreme caution is
 * advised: the <tt>equals</tt> and <tt>hashCode</tt> methods are no longer
 * well defined on such a map.
 *
 * <p>All general-purpose map implementation classes should provide two
 * "standard" constructors: a void (no arguments) constructor which creates an
 * empty map, and a constructor with a single argument of type <tt>Map</tt>,
 * which creates a new map with the same key-value mappings as its argument.
 * In effect, the latter constructor allows the user to copy any map,
 * producing an equivalent map of the desired class.  There is no way to
 * enforce this recommendation (as interfaces cannot contain constructors) but
 * all of the general-purpose map implementations in the JDK comply.
 *
 * <p>The "destructive" methods contained in this interface, that is, the
 * methods that modify the map on which they operate, are specified to throw
 * <tt>UnsupportedOperationException</tt> if this map does not support the
 * operation.  If this is the case, these methods may, but are not required
 * to, throw an <tt>UnsupportedOperationException</tt> if the invocation would
 * have no effect on the map.  For example, invoking the {@link #putAll(Map)}
 * method on an unmodifiable map may, but is not required to, throw the
 * exception if the map whose mappings are to be "superimposed" is empty.
 *
 * <p>Some map implementations have restrictions on the keys and values they
 * may contain.  For example, some implementations prohibit null keys and
 * values, and some have restrictions on the types of their keys.  Attempting
 * to insert an ineligible key or value throws an unchecked exception,
 * typically <tt>NullPointerException</tt> or <tt>ClassCastException</tt>.
 * Attempting to query the presence of an ineligible key or value may throw an
 * exception, or it may simply return false; some implementations will exhibit
 * the former behavior and some will exhibit the latter.  More generally,
 * attempting an operation on an ineligible key or value whose completion
 * would not result in the insertion of an ineligible element into the map may
 * throw an exception or it may succeed, at the option of the implementation.
 * Such exceptions are marked as "optional" in the specification for this
 * interface.
 *
 * <p>Many methods in Collections Framework interfaces are defined
 * in terms of the {@link Object#equals(Object) equals} method.  For
 * example, the specification for the {@link #containsKey(Object)
 * containsKey(Object key)} method says: "returns <tt>true</tt> if and
 * only if this map contains a mapping for a key <tt>k</tt> such that
 * <tt>(key==null ? k==null : key.equals(k))</tt>." This specification should
 * <i>not</i> be construed to imply that invoking <tt>Map.containsKey</tt>
 * with a non-null argument <tt>key</tt> will cause <tt>key.equals(k)</tt> to
 * be invoked for any key <tt>k</tt>.  Implementations are free to
 * implement optimizations whereby the <tt>equals</tt> invocation is avoided,
 * for example, by first comparing the hash codes of the two keys.  (The
 * {@link Object#hashCode()} specification guarantees that two objects with
 * unequal hash codes cannot be equal.)  More generally, implementations of
 * the various Collections Framework interfaces are free to take advantage of
 * the specified behavior of underlying {@link Object} methods wherever the
 * implementor deems it appropriate.
 *
 * <p>Some map operations which perform recursive traversal of the map may fail
 * with an exception for self-referential instances where the map directly or
 * indirectly contains itself. This includes the {@code clone()},
 * {@code equals()}, {@code hashCode()} and {@code toString()} methods.
 * Implementations may optionally handle the self-referential scenario, however
 * most current implementations do not do so.
 *
 * <p>This interface is a member of the
 * <a href="{@docRoot}/../technotes/guides/collections/index.html">
 * Java Collections Framework</a>.
 *
 * @param <K> the type of keys maintained by this map
 * @param <V> the type of mapped values
 *
 * @author  Josh Bloch
 * @see HashMap
 * @see TreeMap
 * @see Hashtable
 * @see SortedMap
 * @see Collection
 * @see Set
 * @since 1.2
 */

==============================================================

下面的链接是 HashMap实现原理:

HashMap的实现原理 (讲的不是很清晰)

==============================================================

HashMap  的数据结构: http://blog.csdn.net/vking_wang/article/details/14166593

look the picture:
pic 1

pic 2


HashMap put source:

1)put

疑问:如果两个key通过hash%Entry[].length得到的index相同,会不会有覆盖的危险?
  这里HashMap里面用到链式数据结构的一个概念。上面我们提到过Entry类里面有一个next属性,作用是指向下一个Entry。打个比方, 第一个键值对A进来,通过计算其key的hash得到的index=0,记做:Entry[0] = A。一会后又进来一个键值对B,通过计算其index也等于0,现在怎么办?HashMap会这样做:B.next = A,Entry[0] = B,如果又进来C,index也等于0,那么C.next = B,Entry[0] = C;这样我们发现index=0的地方其实存取了A,B,C三个键值对,他们通过next这个属性链接在一起。所以疑问不用担心。也就是说数组中存储的是最后插入的元素。到这里为止,HashMap的大致实现,我们应该已经清楚了。


    /**
     * Maps the specified key to the specified value.
     *
     * @param key
     *            the key.
     * @param value
     *            the value.
     * @return the value of any previous mapping with the specified key or
     *         {@code null} if there was no such mapping.
     */
    @Override public V put(K key, V value) {
        if (key == null) {
            return putValueForNullKey(value);
        }

        int hash = Collections.secondaryHash(key);
        HashMapEntry<K, V>[] tab = table;
        int index = hash & (tab.length - 1);
        //1  如果key在链表中已存在,则替换为新value
        //  看了好一会儿,终于看明白了。这一过程是,当你新添加的元素 不仅 HashCode 一样。而且Key 也是一样的时候,就是 有重复的数据的时候 需要讲老的数据 替换,保证唯一性!
        for (HashMapEntry<K, V> e = tab[index]; e != null; e = e.next) {
            if (e.hash == hash && key.equals(e.key)) {
                preModify(e);
                V oldValue = e.value;
                e.value = value;
                return oldValue;
            }
        }

        // No entry for (non-null) key is present; create one
        modCount++;
        if (size++ > threshold) {
           //3  当你的 table[] 内存太小的时候就会调用该方法 分配更大的内存空间!
            tab = doubleCapacity();
            index = hash & (tab.length - 1);
        }
        //2  添加实体(其实是 zai'xiaindex替换下来的老的实体)
        // 这里才是真正的加入table[] 数据。 当你的HashCode 一样的时候,就调用这个方法。将老的数据的位置用新的数据替换, 老的数据后移一位!
        addNewEntry(key, value, hash, index);
        return null;
    }

    /**
     * Computes a hash code and applies a supplemental hash function to defend
     * against poor quality hash functions. This is critical because HashMap
     * uses power-of-two length hash tables, that otherwise encounter collisions
     * for hash codes that do not differ in lower or upper bits.
     * Routine taken from java.util.concurrent.ConcurrentHashMap.hash(int).
     * @hide
     */
    public static int secondaryHash(Object key) {
        return secondaryHash(key.hashCode());
    }

2 let me see:

    /**
     * Creates a new entry for the given key, value, hash, and index and
     * inserts it into the hash table. This method is called by put
     * (and indirectly, putAll), and overridden by LinkedHashMap. The hash
     * must incorporate the secondary hash function.
     */
    void addNewEntry(K key, V value, int hash, int index) {
        table[index] = new HashMapEntry<K, V>(key, value, hash, table[index]);
    }

3  当你的 table[] 内存太小的时候就会调用该方法 分配更大的内存空间!
 /**
     * Doubles the capacity of the hash table. Existing entries are placed in
     * the correct bucket on the enlarged table. If the current capacity is,
     * MAXIMUM_CAPACITY, this method is a no-op. Returns the table, which
     * will be new unless we were already at MAXIMUM_CAPACITY.
     */
    private HashMapEntry<K, V>[] doubleCapacity() {
        HashMapEntry<K, V>[] oldTable = table;
        int oldCapacity = oldTable.length;
        if (oldCapacity == MAXIMUM_CAPACITY) {
            return oldTable;
        }
        int newCapacity = oldCapacity * 2;
        HashMapEntry<K, V>[] newTable = makeTable(newCapacity);
        if (size == 0) {
            return newTable;
        }

        for (int j = 0; j < oldCapacity; j++) {
            /*
             * Rehash the bucket using the minimum number of field writes.
             * This is the most subtle and delicate code in the class.
             */
            HashMapEntry<K, V> e = oldTable[j];
            if (e == null) {
                continue;
            }
            int highBit = e.hash & oldCapacity;
            HashMapEntry<K, V> broken = null;
            newTable[j | highBit] = e;
            for (HashMapEntry<K, V> n = e.next; n != null; e = n, n = n.next) {
                int nextHighBit = n.hash & oldCapacity;
                if (nextHighBit != highBit) {
                    if (broken == null)
                        newTable[j | nextHighBit] = n;
                    else
                        broken.next = n;
                    broken = e;
                    highBit = nextHighBit;
                }
            }
            if (broken != null)
                broken.next = null;
        }
        return newTable;
   }



哈希表有多种不同的实现方法

==============================================================

2. Get
获取的思想比较简单。不需要判断有没有重复的元素:
原理:
跟HashCode 获取元素在HashTable中的位置 index. 然后判断Key是不是相同,如果相同取出。 否则循环遍历链表。


    /**
     * Returns the value of the mapping with the specified key.
     *
     * @param key
     *            the key.
     * @return the value of the mapping with the specified key, or {@code null}
     *         if no mapping for the specified key is found.
     */
    public V get(Object key) {
        if (key == null) {
            HashMapEntry<K, V> e = entryForNullKey;
            return e == null ? null : e.value;
        }

        int hash = Collections.secondaryHash(key);
        HashMapEntry<K, V>[] tab = table;
        for (HashMapEntry<K, V> e = tab[hash & (tab.length - 1)];
                e != null; e = e.next) {
            K eKey = e.key;
            // Key code in this line
            if (eKey == key || (e.hash == hash && key.equals(eKey))) {
                return e.value;
            }
        }
        return null;
    }

==============================================================

3. 解决hash冲突的办法

  1. 开放定址法(线性探测再散列,二次探测再散列,伪随机探测再散列)
  2. 再哈希法
  3. 链地址法
  4. 建立一个公共溢出区
Java中hashmap的解决办法就是采用的链地址法。

==============================================================


See the UML 



总结:
HashMap是基于”拉链法“实现的散列表,一般用于单线程,键值都可以为空,支持Iterator(迭代器)遍历
Hashtable是基于”拉链法“实现的散列表,是线程安全的,可以用于多线程程序中。支持Iterator(迭代器)遍历和Enumeration(枚举器)两种遍历方式。
WeakHashMap也是基于”拉链法“实现的散列表,同时是弱键
TreeMap 是有序的散列表,通过红黑树来实现的,键值都不能为空。

==============================================================


写的非常的不错,因为是我的学长 哈哈




参考链接:

http://blog.csdn.net/speedme/article/details/22398395

http://blog.csdn.net/shimiso/article/details/10181801

http://blog.csdn.net/vking_wang/article/details/14166593

http://blog.csdn.net/qq924862077/article/details/48039643

http://liujiacai.net/blog/2015/09/04/java-treemap/