android java 知识点

列表
SoftReference和WeakReference
当try{}中有return时,finally{}中的代码还会不会被执行?
sendMessage和sendToTarget,一个是Handler类的方法, 一个是Message类的方法
Android 更新UI的两种方法——handler和runOnUiThread(runnable)
为什么在方法内创建匿名内部类的对象时, 方法中的局部变量要声明为final的
反射的应用场景
transient关键字
@SuppressWarings注解的作用
什么时候用接口, 什么时候用抽象类.
什么是抽象类和匿名内部类,以及为什么要使用它们
volatile关键字修饰的变量, 对其操作为原子级.
定义static内部类就相当于直接写了一个.java的文件
StringBuffer和StringBuilder的区别
JSONObject optString与getString的区别

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

SoftReference和WeakReference

强引用: 直接的对象引用
软引用 SoftReference : 当一个对象只有软引用存在时,系统内存不足时此对象会被gc回收.

String str=new String("abc");
SoftReference<String> softRef=new SoftReference<String>(str);
String str2 = softRef.get();
if(str2 != null) {
  //直接使用
} else {
  //已经被gc回收
}

弱引用 WeakReference : 当一个对象只有弱引用存在时,此对象会随时被gc回收.
弱引用是最弱的.

String str=new String("abc");
WeakReference<String> weakRef=new WeakReference<String>(str);
String str2 = weakRef.get();
if(str2 != null) {
  //直接使用
} else {
  //已经被gc回收
}
当try{}中有return时,finally{}中的代码还会不会被执行?

yes

public static void main() {
        int a = f_test();
        Log.i("ahking","333, a = " +a);
}

public static int f_test() {
    int a = 0;
    try {
        a = 1;
        Log.i("ahking","111");
        return a;
    } finally {
        Log.i("ahking","222");
        a = 2;
        return a;
    }
}

logcat:

10-22 08:02:33.871  19565-19565/com.qihoo.browser I/ahking﹕ 111
10-22 08:02:33.871  19565-19565/com.qihoo.browser I/ahking﹕ 222
10-22 08:02:33.871  19565-19565/com.qihoo.browser I/ahking﹕ 333, a = 2

结论:
try{}中有return; finally{}也会被执行.
finally{}中如果有return;將覆盖try{}中的return,作为函数的出口. 但不是一个好的编程习惯, 这点了解一下即可, 实际开发中不要这么用.

sendMessage和sendToTarget,一个是Handler类的方法, 一个是Message类的方法
Message message = mHandler.obtainMessage();
message.what = MSG_QUERY_MOBILE_BOOKMARK;
message.obj = infos;
message.sendToTarget();//实际上调用的就是创建message时用的handler对象.

就相当于:

Message msg = Message.obtain(null, MSG_HANDLE_LOCATION_FAILED, 0, 0);
mHandler.sendMessage(msg);

源码:

Handler.java

public final Message obtainMessage()
{
    return Message.obtain(this);
}
public static Message obtain(Handler h) {
    Message m = obtain();
    m.target = h;

    return m;
}
Message.java

Handler target; 

public void sendToTarget() {
    target.sendMessage(this);
}
Android 更新UI的两种方法——handler和runOnUiThread(runnable)

通过handler执行更新UI的任务,是最常用的方法, 这里就不多说了, 除了这个方法, android还为Activity类提供了一个runOnUiThread(runnable)方法, 也可以用来执行更新UI的任务.

创建Activity对象时, 会在它内部创建一个Handler对象, 目的就是不管在UI线程还是非UI线程中, 都能够通过Activity的对象调用runOnUiThread(runnable)去执行一个更新UI的任务. 如果runOnUiThread(runnable)执行在UI线程,那么这个runnable对象立即执行,如果执行在非UI线程, 那么这个runnable对象就被mHandler封装成msg,压入它所关联的消息队列MessageQueue, 等待UI线程空闲时,被UI线程执行.

Activity.java源码:
public class Activity {
    final Handler mHandler = new Handler();
    ...
    public final void runOnUiThread(Runnable action) {
        if (Thread.currentThread() != mUiThread) {
            mHandler.post(action);
        } else {
            action.run();
        }
    }
    ...
}
为什么在方法内创建匿名内部类的对象时, 方法中的局部变量要声明为final的

内部类通常都含有回调,引用那个匿名内部类的函数执行完了就没了,所以内部类中引用外面的局部变量需要是final的,这样在回调的时候才能找到那个变量,而如果是外围类的成员变量就不需要是final的,因为内部类本身都会含有一个外围了的引用(外围类.this),所以回调的时候一定可以访问到。例如下面:

private Animator createAnimatorView(final View view, final int position) {
    MyAnimator animator = new MyAnimator();
    animator.addListener(new AnimatorListener() {
        @Override
        public void onAnimationEnd(Animator arg0) {
            Log.d(TAG, "position=" + position); 
        }
    });
    return animator;
}

内部类回调里访问position的时候createAnimatorView()早就执行完了,position如果不是final的,回调的时候肯定就无法拿到它的值了,因为局部变量在函数执行完了以后就被回收了。
refer:
http://www.zhihu.com/question/21395848

反射的应用场景
使用被隐藏的类和方法.
package com.android.internal.policy;

import android.content.Context;
import android.view.FallbackEventHandler;
import android.view.LayoutInflater;
import android.view.Window;
import android.view.WindowManagerPolicy;

/**
 * {@hide}
 */

public final class PolicyManager {
    private static final String POLICY_IMPL_CLASS_NAME =
        "com.android.internal.policy.impl.Policy";

    private static final IPolicy sPolicy;

    static {
        // Pull in the actual implementation of the policy at run-time
        try {
            Class policyClass = Class.forName(POLICY_IMPL_CLASS_NAME);
            sPolicy = (IPolicy)policyClass.newInstance();
        //这里不能直接 sPolicy = new Policy();而必须要用反射的原因是Policy类的声明也是被隐藏的,尽量Policy类在"impl"子包中, 也必须使用反射才能找到, 不能直接import com.android.internal.policy.impl.Policy; 然后new Policy().
        } catch (ClassNotFoundException ex) {
            throw new RuntimeException(
                    POLICY_IMPL_CLASS_NAME + " could not be loaded", ex);
    }

    // Cannot instantiate this class
    private PolicyManager() {}

    // The static methods to spawn new policy-specific objects
    public static Window makeNewWindow(Context context) {
        return sPolicy.makeNewWindow(context);
    }
    ...
}
transient关键字

加transient关键字的属性, 不会被序列化, 比如银行卡密码等不希望在网络中传输, 就需要加上这个关键字.

public class SerializableCookie implements Serializable {
        private static final long serialVersionUID = 6374381828722046732L;

        private transient final Cookie cookie;
        private transient BasicClientCookie clientCookie;
}


public class HashSet<E> extends AbstractSet<E> implements Set<E>, Cloneable, Serializable {
    static final long serialVersionUID = -5024744406713321676L;
    private transient HashMap<E, Object> map;

}
@SuppressWarings注解的作用

@SuppressWarings注解
作用:用于抑制编译器产生警告信息。
refer to : http://www.cnblogs.com/fsjohnhuang/p/4040785.html

@SuppressWarnings("UnusedDeclaration")
public class StrictANRWatchDog extends Thread {
//这个类中的某个方法如果没有被使用的话, IDE也不会给出警告信息, 免得代码看起来很繁乱.
什么时候用接口, 什么时候用抽象类.

abstract class中,可以有自己的数据成员,
abstract class中,可以有一部分abstarct成员方法, 其他的也可以是一般的成员方法(给出成员方法的实现).
interface中,一般不定义数据成员,如果定义的话, 也是public static final常量,且必须给其初值.
interface中,所有的成员方法都是abstract的,都没有方法的实现, 只是abstract关键字给省略了.

//abstract class
public abstract class Reader implements Readable, Closeable {

    protected Object lock;

    protected Reader() {
        lock = this;
    }

    public abstract void close() throws IOException;

    public void mark(int readLimit) throws IOException {
        throw new IOException();
    }
...
}
// interface
public interface ResponseDelivery {

    public void postResponse(Request<?> request, Response<?> response);

    public void postResponse(Request<?> request, Response<?> response, Runnable runnable);

    public void postError(Request<?> request, VolleyError error);
}

什么是抽象类和匿名内部类,以及为什么要使用它们

什么是抽象函数
只有函数的定义, 没有函数体的函数被成为抽象函数.
abstract void eat();

什么是抽象类
使用abstract定义的类被称之为抽象类.

  1. 抽象类不能够生成对象, 但是却可以有构造函数, 提供给子类通过super()方法进行调用.
  2. 如果一个类当中包含有抽象函数, 那么这个类必须被声明为抽象类.
  3. 如果一个类中没有抽象函数, 那么这个类也可以被声明为抽象类.

为什么使用抽象类
架构设计的时候为什么要有意识的使用抽象类.
定义一个通用的打印机的基类.
方案1:

class Printer {
    void open() {
        System.out.println("open()");
    }

    void close() {
        System.out.println("close()");
    }

    //这里给出一个空的方法体, 让具体的子类去override进行实现.
    void print() {
    }
}

方案2:

abstract class Printer {
    void open() {
        System.out.println("open()");
    }

    void close() {
        System.out.println("close()");
    }

    abstract void print(); //把print()定义为抽象方法.
}

2个方案其实都能实现同样的功能.
抽象类中的抽象方法的设计价值是,通过编译器保证了子类确实对抽象方法进行了实现,如果用一个空函数体的方法代替抽象方法就无法通过编译器去保证子类对这个方法进行了实现.

什么是匿名内部类
匿名内部类的使用地方是:用在方法的参数,一般是new一个接口的对象出来使用.

handler.postDelayed(new Runnable() {
    @Override
    public void run() {
            Log.i(TAG, "Sending file " + filename);
            sendCrashData(context, filename, finalJavaCrashCountUploader);
    }
}, delayTime);

这里的new Runnable() {}就是一个匿名内部类的对象.

开发中要注意的点:
如果子类的构造方法中没有显示的调用父类构造方法,则系统默认调用父类无参数的构造方法.

class Chinese extends Person {
    Chinese() {
        System.out.println("Chinese的构造方法");
    }
    
    void eat() {
        System.out.println("用筷子吃饭");
    }

}

等同于:
class Chinese extends Person {
    Chinese() {
        super();
        System.out.println("Chinese的构造方法");
    }
    
    void eat() {
        System.out.println("用筷子吃饭");
    }

}
volatile关键字修饰的变量, 对其操作为原子级.

有一个例外是, 如果当前值与该变量以前的值相关,
那么volatile关键字不起作用,也就是说如下的表达式都不是原子操作:

public static volatile int n = 0;
n = n + 1;
n++;

在这种情况下,可使用synchronized关键字实现对其变量操作的原子性.

public static int n = 0;
public static synchronized void inc()  
{  
        n++;  
}  

详见:
http://developer.51cto.com/art/200906/132344.htm(初学Java多线程:慎重使用volatile关键字)

定义static内部类就相当于直接写了一个.java的文件

主要是防止内存泄露,使用static 相当于直接写了一个.java的文件,
与外部类就没有依赖关系了,详见
http://stackoverflow.com/questions/70324/java-inner-class-and-static-nested-class
普通内部类隐含有个成员变量this$0, 持有对外部类的引用, this$0变量在内部类的默认构造方法中, 用外部类对象对其进行的赋值.

StringBuffer和StringBuilder的区别

1.使用String类的场景:在字符串不经常变化的场景中可以使用String类,例如常量的声明、少量的变量运算。

2.使用StringBuffer类的场景:在频繁进行字符串运算(如拼接、替换、删除等),并且运行在多线程环境中,则可以考虑使用StringBuffer,例如XML解析、HTTP参数解析和封装。

3.使用StringBuilder类的场景:在频繁进行字符串运算(如拼接、替换、和删除等),并且运行在单线程的环境中,则可以考虑使用StringBuilder,如SQL语句的拼装、JSON封装等。

结论:
StringBuffer是线程安全的,有加锁开销,效率略低。StringBuilder非线程安全,不用加锁,效率更高。一般字符串相加不会有多线程操作,所以推荐使用StringBuilder.

很少碰到这种情况, StringBuilder sb = new StringBuilder(); 然后在2个线程中, 同时分别调用sb.append("abc")和sb.append("123"); 在这种情况下, 最终sb的结果就会不符合预期.

但很少使用多线程对一个字符串进行相加操作, 因此大多数情况下, 优先使用StringBuilder > StringBuffer.

JSONObject optString与getString的区别

getString(String name)与optString(String name),功能一样,只是当name key 不存在时,getString(String name)抛出异常错误,optString(String name)返回空值.

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,098评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,213评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,960评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,519评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,512评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,533评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,914评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,574评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,804评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,563评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,644评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,350评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,933评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,908评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,146评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,847评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,361评论 2 342

推荐阅读更多精彩内容

  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,560评论 18 399
  • 一:java概述:1,JDK:Java Development Kit,java的开发和运行环境,java的开发工...
    ZaneInTheSun阅读 2,627评论 0 11
  • (一)Java部分 1、列举出JAVA中6个比较常用的包【天威诚信面试题】 【参考答案】 java.lang;ja...
    独云阅读 7,062评论 0 62
  • 朋友圈里似乎每处都充满了过节的气息,无不提醒自己明年就在明天之后,我不知道用什么样的心情去迎接。反复回忆着2016...
    风起来的时光jydyh阅读 1,348评论 0 0
  • W6L3:1. (1)因为加工制造位于产业链附加值曲线的最底端,利润相对薄弱,企业如果要获得更多的附加值,就必须向...
    5a867ebcd3db阅读 98评论 0 0