(Java面试之知识点串烧)

串一串,串一串

这里写图片描述

一、

1、起源
Java于1995年由Sun公司推出,由Java之父詹姆斯·戈士林设计而成,最初的名字是OAK,在95年被命名为Java,正式发布。
2、计算机语言
计算机高级编程语言按其程序的执行方式可以分为两种:编译型,解释型

<1>.编译型语言是指使用专门的编译器、针对特定平台(操作系统)将某种高级语言源程序一次性“翻译”成可被该平台硬件运行的机器码(包括指令和操作数),并包装成该平台的操作系统所能识别和运行的格式。这种语言的程序执行时效率高,可以脱离开发环境独立运行,但如果要移植必须修改源程序,或者针对不同的平台采用不同的编译器进行重新编译。现在的多试高级语言,如c,c++,Pascal,LISP等都是编译型的。

<2>.解释型是指用专门的解释器将某种高级语言源程序逐条解释成特定平台的机器码指令并立即执行,解释一句执行一句,而不进行整体的编译和链接处理。

<3>.java语言是解释型和编译型的结合,先采用通用的java编译器将java源程序编译成为与平台无关的中间产物,然后利用java虚拟机(JVM:Java Virtual Maching)进行解释执行。
3、第一个程序
HelloWorld案例
public class HelloWorld{
public static void main(String[] args){
System.out.println(“你好,Java”)
}
}
4、数据类型和变量( 声明 赋值)
数据类型:基本(简单)数据类型 ,引用数据类型
基本数据类型8种及其默认初始值:byte 0 short 0 int 0 long 0L float 0.0f double 0.0 char ” ” boolean true
引用数据类型默认初始值都是null。
变量:
全局(成员)变量:在类体中,成员变量在整个有效。
局部变量 :在方法体中的属性称为局部变量,必须赋值才能被使用。
5、语句
分为:顺序语句 分支语句 循环语句(大部分在c c++中都相似)
foreach语句 :
此语句是for语句的特殊简化版,不能完全取代for语句,但任何foreach语句都能改写成for语句。 语法如下:
for(元素变量 x:遍历对象obj){
引用了x的Java语句;

例:

int arr[] = {7,5,6,2};//声明一维数组
for(int x:arr){//遍历数组
 Syste.out.println(x);//将输出数组arr的各个数值7,5,6,2
}

break:跳出本次循环
continue:跳出本次循环continue以下的代码块
return:返回代参的循环值。无参的最后加return不会出错。
6、冒泡排序(有点重要,面试中可能会问到)
Java代码

int arr[] = {5,84,65,12,477,9,6,45,547};
int temp = 0;
for(int i = 0; i<arr.length - 1;i++){
   for(int j = 0;j<arr.length - 1- i;j++){
    if(arr[j] >arr[j+1]){
        temp = arr[j+1];
        arr[j+1] = arr[j];
        arr[j] = temp;
        }
    }
  for(int i<=0;i<arr.length;i++){
       Syste.out.println(arr[i])};
}

一个排序的方法 Array.sort(arr):从小到大排序数组arr的值。

7、类和对象
类是一系列对象的抽象,而对象是类的一个具体实例。
类:属性 、方法、构造器
构造器:体统默认提供无参构造器。
8、字符串
String与StringBuffer的区别
简单地说,就是一个变量和常量的关系。StringBuffer对象的内容可以修改;而String对象一旦产生后就不可以被修改,重新赋值其实是两个对象。

  StringBuffer是线程安全的,在多线程程序中也可以很方便的进行使用,但是程序的执行效率相对来说就要稍微慢一些。

StringBuffer的常用方法
StringBuffer类中的方法要偏重于对字符串的变化例如追加、插入和删除等,这个也是StringBuffer和String类的主要区别。
1、append方法
public StringBuffer append(boolean b)
该方法的作用是追加内容到当前StringBuffer对象的末尾,类似于字符串的连接。调用该方法以后,StringBuffer对象的内容也发生改变,例如:
StringBuffer sb = new StringBuffer(“abc”);
sb.append(true);
则对象sb的值将变成”abctrue”。

<1>
char a[]={‘g’,’o’,’o’,’d’};
String s = new String(a);等价于:String s = new String(“good”);
<2> String(char a[],int offset,int length)
提取字符串数组中的一部分
<3>indexOf(String s)
返回字符串s在指定字符串中首次出现的索引位置,调用时,会从当前字符串的开始位置搜索s的位置;如果没有,返回-1。
<4>lastIndexOf(String s)
返回制定字符串s最后一次出现的索引位置。调用时会从当前字符串的位置开始位置检索参数字符串s,并将最后一次出现s的索引位置返回;如果没有检索到,则返回-1。
<5>substring(int beginIndex)
从指定的索引位置截取直到字符串结束的子串。
substring(int beginIndex,int endIndex)
截取从某一索引位置到另一索引位置的子串。
<6>trim()
去掉字符串首部和尾部的空格
<7>str.replace(char oldChar,char newChar)
字符或字符串的替换
<8>判断字符串的开始和结尾
startsWith()方法 endsWith()方法
<9>大小写互换

         String s = "wSDEtrgda";
         String s2 = "";
    for (int i = 0; i < s.length(); i++) {
            char c = s.charAt(i);//得到地址为i的字符
            if (Character.isLowerCase(c)) {//判断c是不是小写字母
                c = Character.toUpperCase(c);//小写变大写
            } else {
                c = Character.toLowerCase(c);//大写变小写
            }
            s2 += c;
        }
        System.out.println(s2);
   }
}

9.数组
随机产生一个4x4列矩阵,计算并输出对角线之积

public class Work2 {

    public static void main(String[] args) {
        Random rd = new Random();//产生随机数
        int[][] num = new int[4][4];
        for (int i = 0; i < 4; i++) {
            for (int j = 0; j < 4; j++) {
                num[i][j] = rd.nextInt(100);
            }
            System.out.println(Arrays.toString(num[i]));//Arrays.toString(int[] a) 返回指定数组内容的字符串表示形式。
        }
        int sum1 = 1;
        int sum2 = 1;
        for (int i = 0; i < num.length; i++) {
            sum1 *=num[i][i];
            sum2 *=num[i][3-i];
        }
        System.out.println("正对角线:"+sum1+" 副对角线:  "+sum2);
    }
}
[20, 35, 85, 73]
[13, 58, 10, 61]
[59, 98, 10, 92]
[1, 44, 33, 89]
正对角线:1032400 副对角线:  71540

10、Java的三大特性:封装、继承、多态
<1>封装是面向对象编程的核心思想。将对象的属性和行为隐藏在类的内部,其载体是类。提供一个外部能够访问的方法,在这个方法中做一些判断。
封装思想保证了类内部数据结构的完整性,避免了外部操作对内部数据的影响,提高了程序的可维护性。
<2>子类继承父类的属性和方法,方便了类的复用,提高效率,减少出错几率,缩短开发时间。
方法重写:@override 在子类中 方法名相同 返回值类型相同 参数列表相同,访问修饰符不能比父类更严格。
方法重载:同一个类中,方法名相同,参数列表不同。
final 关键字 最终的
修饰的类,不能被继承;修饰的方法,不能被重写;修饰的属性,不能被修改。
super 关键字
用来继承父类的属性和方法。调用父类的构造器,super(name,age);必须写在第一行。
<3>多态
父类的引用指向不同的子类对象。
11、异常
<1>
捕捉异常:try{
//程序代码块
}catch(Exceptiontype1 e){
//对Exceptiontype1的处理
}catch(Exceptiontype2 e){
//对Exceptiontype2的处理
}……
finall{
//程序块
}
捕获异常结构由try,catch,finally3部分构成。其中,try语句块中存放的是可能发生异常的Java语句;catch程序块存放在try语句块之后,用来激发被捕获的异常;finally语句块是异常处理结构的最后执行部分,无论try块中的代码如何退出,都将执行finally块。
<2>
使用throws,throw关键字抛出异常

public class restudent {
    static int quotinet(int x, int y) throws MyException {
        if (y < 0) {
            throw new MyException("除数不能是负数");
        }
        return x / y;
    }

    public static void main(String[] args) {
        try {
            int result = quotinet(3, -1);
        } catch (MyException e) {
            System.out.println(e.getMessage());
            // TODO: handle exception
        } catch (Exception e) {
            System.out.println("程序发生了其它异常");
            // TODO: handle exception
        }
    }
}

12、集合类
<1>Collection接口
接口 Iterator 对 collection 进行迭代的迭代器。
方法:
hasNext()
如果仍有元素可以迭代,则返回 true。
next()
返回迭代的下一个元素。
remove()
从迭代器指向的 collection 中移除迭代器返回的最后一个元素(可选操作)。


public class restudent {

    public static void main(String[] args) {
     Collection<String> list = new ArrayList<>();//实例化集合类对象
     list.add("a");//向集合中添加数据
     list.add("b");
     Iterator<String> it = list.iterator();//创建器
     while(it.hasNext()){//判断是否有下一个元素
         String str = it.next();//获取集合中元素
         System.out.println(str);
     }

    }
}

<2>List集合 可包含重复的对象有序
常用的实现类有arraylist和linkedlist:
arraylist类实现了可变的数组,语序保存所有的元素,包括null,可以根据索引位置对集合进行快速的随机访问,缺点是速度较慢;
linkedlist采用链表结构保存对象,优点是便于向集合中插入和删除对象,效率较高,但对于随机访问效率较低。
List接口继承了Collection接口,因此包含其中的所有方法,此外,list接口还定义了以下两个重要的方法:
get(int index):获取制定索引位置的元素
set(int index,Object obj):将集合中制定索引位置的对象修改为指定的对象。
List接口通常有Arraylist和LinkedList(采用链表结构保存对象)

ArrayList<Student> list = new ArrayList<>();
         Student s = new Student("李三", "北京");
         list.add(new Student("李四", "北京"));
         list.add(new Student("张三", "上海"));
         list.add(new Student("王五", "青岛"));
         list.add(new Student("马六", "烟台"));
         for (Student stu : list) {
             System.out.println(stu.getName()+stu.getHometown());

        }

<3>Set集合 不能包含重复的对象
Set接口常用的实现类有HashSet类和TreeSet类
HashSet类实现Set接口,由哈希表支持,没有顺序,此类允许使用null
TreeSet类不仅实现了Set接口,在遍历集合时按照自然顺序递增排序,也可以按照制定比较器递增顺序排序。
<4>Map集合 不能包含重复的键,每个键最多只能映射到一个值
接口 Map

public static void main(String[] args) {
        Map<String, String> map = new HashMap<>();
        map.put("1", "zhangsan");
        map.put("2", "lisi");
        map.put("3", "wangwu");
        Set<String> set = map.keySet();
        Iterator<String> it = set.iterator();

        while (it.hasNext()) {
            System.out.println(it.next());/*输出:1
                                                 2
                                                 3*/
        }
        Collection<String> se = map.values();
        it = se.iterator();
        while (it.hasNext()) {
            System.out.println(it.next());/*输出:zhangsan
        }                                        lisi
                                                 wangwu*/
    }
}

k,v
类型参数:
K - 此映射所维护的键的类型
V - 映射值的类型
将键映射到值的对象。一个映射不能包含重复的键;每个键最多只能映射到一个值。

public static void main(String[] args) {
        Map<String, String> map = new HashMap<>();
        student s1= new student("1", "zhangsan");//创建学生对象
        student s2= new student("2", "lisi");
        student s3= new student("3", "wangwu");
        map.put(s1.getId(),s1.getName());//将对象添加到集合中
        map.put(s2.getId(),s2.getName());
        map.put(s3.getId(),s3.getName());
        Set<String> set = map.keySet();//获取Map集合中的key对象集合
        Iterator<String> it = set.iterator();
        while(it.hasNext()){
            String str = it.next();
            String name = map.get(str);//遍历Map集合
            System.out.println(str+"  "+name);
        }
/*输出   1  zhangsan
        2  lisi
        3  wangwu   */

13、输入输出流
输入流:InputStream(字节输入流)Reader(字符输入流)
输出流:OutputStream(字节输出流)Writer(字符输出流)

      InputStream is = socket.getInputStream();//监听连接进来的客户,读字节
      InputStreamReader isr = new InputStreamReader(is);//读字符
      BufferedReader br = new BufferedReader(isr);//读一行

<1>文件的创建和删除

    File f=new File("d://11.txt");
        if(!f.exists()){//如果没有此文件
            try {
                f.createNewFile();//创建新文件
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }else{
            f.delete();//如果存在删除文件
    }

<2>输入流 InputStream读 ,输出流OutputStream写

    String s ="开辟鸿蒙,谁为情种?都只为风月情浓。";
        try {
            byte[] array = s.getBytes();
            FileOutputStream fos = new FileOutputStream(f);
            fos.write(array);//或者fos.write("开辟鸿蒙,谁为情种?都只为风月情浓。");
            fos.flush();//刷新此输出流并强制写出所有缓冲的输出字节
            fos.close();//关闭此输出流并释放与此流有关的所有系统资源
            System.out.println("写入文件完成");
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }catch (IOException e) {
            e.printStackTrace();
            // TODO: handle exception
        }
//        读文件
        byte[] array = new byte[128];
        try {
            FileInputStream fis = new FileInputStream(f);
            int num = fis.read(array);
            while (num != -1) {
                System.out.println(new String(array, 0, num));
                num = fis.read(array);
            }
            fis.close();
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
            // TODO: handle exception
        }

FileOutputStream fos = new FileOutputStream(f);//按字节写
OutputStreamWriter wr = new OutputStreamWriter(fos);//写字符BufferedWriter bu = new BufferedWriter(wr);//写一行

FileInputStream fio = new FileInputStream(f);//按字节读
InputStreamReader reader = new InputStreamReader(fio);//读字符 BufferedReader buffer = new BufferedReader(reader);//读一行

进程和线程

进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位.
线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.

进程和线程的主要差别在于它们是不同的操作系统资源管理方式。进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响,而线程只是一个进程中的不同执行路径。线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间,一个线程死掉就等于整个进程死掉,所以多进程的程序要比多线程的程序健壮,但在进程切换时,耗费资源较大,效率要差一些。但对于一些要求同时进行并且又要共享某些变量的并发操作,只能用线程,

sleep和wait的区别

1、这两个方法来自不同的类分别是,sleep来自Thread类,和wait来自Object类。

sleep是Thread的静态类方法,谁调用的谁去睡觉,即使在a线程里调用了b的sleep方法,实际上还是a去睡觉,要让b线程睡觉要在b的代码中调用sleep。

2、最主要是sleep方法没有释放锁,而wait方法释放了锁,使得其他线程可以使用同步控制块或者方法。

sleep不出让系统资源;wait是进入线程等待池等待,出让系统资源,其他线程可以占用CPU。一般wait不会加时间限制,因为如果wait线程的运行资源不够,再出来也没用,要等待其他线程调用notify/notifyAll唤醒等待池中的所有线程,才会进入就绪队列等待OS分配系统资源。sleep(milliseconds)可以用时间指定使它自动唤醒过来,如果时间不到只能调用interrupt()强行打断。

Thread.Sleep(0)的作用是“触发操作系统立刻重新进行一次CPU竞争”。

3、使用范围:wait,notify和notifyAll只能在同步控制方法或者同步控制块里面使用,而sleep可以在任何地方使用
synchronized(x){
x.notify()
//或者wait()
}

4、sleep必须捕获异常,而wait,notify和notifyAll不需要捕获异常

Service 两种启动方式

  Service的生命周期Service的生命周期方法比Activity少一些,只有onCreate,onStart,onDestroy
  我们有两种方式启动一个Service,他们对Service生命周期的影响是不一样的。
  
  1通过startService
  Service会经历onCreate->onStart
  stopService的时候直接onDestroy
  
  如果是调用者(TestServiceHolder)自己直接退出而没有调用stopService的
  话,Service会一直在后台运行。
  下次TestServiceHolder再起来可以stopService。
  
  2通过bindService
  Service只会运行onCreate,这个时候TestServiceHolder和TestService绑定在一起
  
  TestServiceHolder退出了,Srevice就会调用onUnbind->onDestroyed
  所谓绑定在一起就共存亡了。
使用startService()方法启用服务,调用者与服务之间没有关连,即使调用者退出了,服务仍然运行。
使用bindService()方法启用服务,调用者与服务绑定在了一起,调用者一旦退出,服务也就终止,大有“不求同时生,必须同时死”的特点。
  
  如果打算采用Context.startService()方法启动服务,在服务未被创建时,系统会先调用服务的onCreate()方法,接着调用onStart()方法
如果调用startService()方法前服务已经被创建,多次调用startService()方法并不会导致多次创建服务,但会导致多次调用onStart()方法
采用startService()方法启动的服务,只能调用Context.stopService()方法结束服务,服务结束时会调用onDestroy()方法。

  如果打算采用Context.bindService()方法启动服务,在服务未被创建时,系统会先调用服务的onCreate()方法,接着调用onBind()方法。
这个时候调用者和服务绑定在一起,调用者退出了,系统就会先调用服务的onUnbind()方法,接着调用onDestroy()方法。

在Android中实现异步任务机制有两种方式,Handler和AsyncTask。

Handler模式需要为每一个任务创建一个新的线程,任务完成后通过Handler实例向UI线程发送消息,完成界面的更新,这种方式对于整个
过程的控制比较精细,但也是有缺点的,例如代码相对臃肿,在多个任务同时执行时,不易对线程进行精确的控制。

andriod提供了Handler 和 Looper 来满足线程间的通信。Handler先进先出原则。Looper类用来管理特定线程内对象之间的消息交换(MessageExchange)。

1)Looper: 一个线程可以产生一个Looper对象,由它来管理此线程里的MessageQueue(消息队列)。
2)Handler: 你可以构造Handler对象来与Looper沟通,以便push新消息到MessageQueue里;或者接收Looper从Message Queue取出)所送来的消息。
3) Message Queue(消息队列):用来存放线程放入的消息。

为了简化操作,Android1.5提供了工具类android.os.AsyncTask,它使创建异步任务变得更加简单,不再需要编写任务线程和Handler实例即可完成相同的任务。

例子:http://blog.csdn.net/liuhe688/article/details/6532519

接口和抽象类有什么区别

你选择使用接口和抽象类的依据是什么?

接口和抽象类的概念不一样。接口是对动作的抽象,抽象类是对根源的抽象。
抽象类表示的是,这个对象是什么。接口表示的是,这个对象能做什么。比如,男人,女人,这两个类(如果是类的话……),他们的抽象类是人。说明,他们都是人。
人可以吃东西,狗也可以吃东西,你可以把“吃东西”定义成一个接口,然后让这些类去实现它.
所以,在高级语言上,一个类只能继承一个类(抽象类)(正如人不可能同时是生物和非生物),但是可以实现多个接口(吃饭接口、走路接口)。
第一点. 接口是抽象类的变体,接口中所有的方法都是抽象的。而抽象类是声明方法的存在而不去实现它的类。
第二点. 接口可以多继承,抽象类不行
第三点. 接口定义方法,不能实现,而抽象类可以实现部分方法。
第四点. 接口中基本数据类型为static 而抽类象不是的。

socket机制

在Java中,基于TCP协议实现网络通信的类有两个:在客户端的Socket类和在服务器端的ServerSocket类。

我们可以简单的把Socket理解为一个可以连通网络上不同计算机程序之间的管道,把一堆数据从管道的A端扔进去,则会从管道的B端(也许同时还可以从C、D、E、F……端冒出来)。管道的端口由两个因素来唯一确认,即机器的IP地址和程序所使用的端口号。

客户端要知道服务哭的IP地址以及端口号,需要主动跟服务器建立连接,对于TCP协议,连接建立后才可以开始传输数据,使用connect函数建立连接,原型如下:
int connect(int sockfd, const struct sockaddr *addr, socklen_t len);
addr: 服务器地址 addrlen:服务器地址结构体长度。

线程安全和不安全

线程安全就是多线程访问时,采用了加锁机制,当一个线程访问该类的某个数据时,进行保护,其他线程不能进行访问直到该线程读取完,其他线程才可使用。不会出现数据不一致或者数据污染。
线程不安全就是不提供数据访问保护,有可能出现多个线程先后更改数据造成所得到的数据是脏数据

Java语言的关键字,当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码。

 当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。
 也就是说,当一个线程访问object的一个synchronized(this)同步代码块时,它就获得了这个object的对象锁。结果,其它线程对该object对象所有同步代码部分的访问都被暂时阻塞。

线程阻塞
阻塞指的是暂停一个线程的执行以等待某个条件发生(如某资源就绪),学过操作系统的同学对它一定已经很熟悉了。Java 提供了大量方法来支持阻塞。
1. sleep() 方法, 2. wait() 和 notify() 方法

ContentProvider

当应用继承ContentProvider类,并重写该类用于提供数据和存储数据的方法,就可以向其他应用共享其数据。虽然使用其他方法也可以对外共享数据,但数据访问方式会因数据存储的方式而不同,如:采用文件方式对外共享数据,需要进行文件操作读写数据;采用sharedpreferences共享数据,需要使用sharedpreferences API读写数据。而使用ContentProvider共享数据的好处是统一了数据访问方式。

android知识点

一、android系统框架
Linux内核 C C++开源库 FrameWork Application
二、四大组件
Activity Service BroadCastReceiver ContentProvider
三、Activity生命周期

四、Activity的启动方式
直接启动Activity

显示启动 Intent intent =new Intent(当前的Context,目标Actifvity名称);

隐式启动Intent intent =new Intent(“在Manifest.xml中注册的Action”);
StartActivityForResult
调用startActivityForResult方法,在此Activity中覆写onActivityResult方法,在目标的Activity中调用setResult的方法,关闭该界面,系统会自动回调上一个界面的onActivityResult方法

五、启动模式

1 standard 默认调用 会生成一个新的Activity,并将此Activity放置到栈顶
2 singleTop 启动的目标Activity如果在栈顶不会生成新的实例(新的Activity对象),如果不在栈顶会生成新的实例,并将该实例放置到栈顶
3 singleTask 启动的目标Activity如果存在于堆栈中,会把所有处于该Activity以上的所有活动弹出出栈将此Activity显示。如果不存在,新生成一个目标Activity的实例,并将该实例放置到栈顶
4 singleInstance 该Activity在整个应用程序中只存在一个实例,该实例独占一个堆栈,该栈中只存在这一个活动

六、Android回调方法

在Android中所有on开头的方法都是回调方法,回调方法由android系统自动调用,不能在方法中主动调用。举个例子Activity的onCreate 自定义View中的onDraw方法,SqliteOpenHelper中的onCreate onUpgrade;

七、五大布局 GridLayout

LinearLayout RelativeLayout FrameLayout TableLayout AbsluteLayout GrideLayout TabLayout

八、dp px sp

px像素
Dp Android推出的相对像素,在一英寸的屏幕上存在160px此时1dp=1px,存在320px则1dp=2px
Sp 功能和dp一致,但是是设置字体大小
九、屏幕适配
使用LinearLayout RelitaiveLayout weight margin padding。Android碎片化,适配不同分辨率不同尺寸的终端设备。不能使用绝对值,要使用dp。得到屏幕分辨率按比例动态设置。不允许使用AbsluteLayout. Layout中和代码中不出现值,将所有的值放置到values中的dimens中

padding margin都是边距的含义,关键问题得明白是什么相对什么的边距.padding是控件的内容相对控件的边缘的边距.margin是控件边缘相对父空间的边距.
十、国际化
代码中不出现中文,全部使用values中的strings的引用,通过values-xx进行国际化。
Values文件夹可以设置不同的国家对应的值 values-zh values-ja values-en
十一、一般控件
TextView
Button drawable下的seletor shape 渐变( 线性 圆形 扇形)
CheckBox 替换原生图片 android:button
RadioButton 设置默认选中 setChecked(true)
RadioGroup 和ViewPager搭配选项卡
Progressbar 圆形进度条 条形进度条
Seekbar 条形拖动条
Ratingbar 评分
ImageView 8中scaleTyple(matrix fitXY fitStart fitCenter fitEnd center centerInside centerCrop)
ImageView中ScaleType属性可用来设置image的填充方式,主要通过以下两种途径:1、XML文件中设置android:scaleType属性。2、代码中使用函数setScaleType(ScaleType scaleType)来设定。目前内置的填充方式有如下8种:
CENTER /center 按图片的原来size居中显示,当图片长/宽超过View的长/宽,则截取图片的居中部分显示
CENTER_CROP / centerCrop 按比例扩大图片的size居中显示,使得图片长(宽)等于或大于View的长(宽)
CENTER_INSIDE / centerInside 将图片的内容完整居中显示,通过按比例缩小或原来的size使得图片长/宽等于或小于View的长/宽
FIT_CENTER / fitCenter 把图片按比例扩大/缩小到View的宽度,居中显示
FIT_END / fitEnd 把图片按比例扩大/缩小到View的宽度,显示在View的下部分位置
FIT_START / fitStart 把图片按比例扩大/缩小到View的宽度,显示在View的上部分位置
FIT_XY / fitXY 把图片不按比例 扩大/缩小到View的大小显示
MATRIX / matrix 用矩阵来绘制

src background区别 src是imageview设置图片资源的方法。Background是所有的view都可以设置,默认是拉伸到该view的宽高
ImageButton
十二、高级控件
Toast 不响应事件,只要有Context就能弹出
Notification 通知
PendingIntent intent 区别 PendingIntent是延时意图不依赖于应用,应用关闭掉该PendingIntent依然起作用,他是由Android系统去维护的,Intent依赖于应用本身,应用关闭了,Intent不会起作用。
PedingIntent应用的场景 闹钟 Notification 短信发送
Notification主要用于推送
Dialog AlertDialog 依赖于Activity。记得使用AlertDiaog.Builder
自定义Dialog 设置contentView
PopupWindow 加动画 设置背景
DatePickerDialog TimePickerDialog
自定义的wheelView
ScrollView HoritalSrcollView 只允许有一个子view,该子view中可以拥有多个view
十三、AdapterView
1 ListView MVC 低耦合
2 Mdole View Controller
ListView中的MVC设计,Modle是存放数据的集合,V是View是adapter中的getView方法返回的view。C是Controller在listView中设置的onItemClickListener.
M:model:指的是用来封装信息的对象。
V:view:用来显示model中封装的信息的组件。
C:controller:用来控制model中的信息怎么输出到view中的
3 recyclerView遵循mvc的变种mvp模式
View
View 通常来说就是有Activity、Fragment实现的,View会包含一个或多个Presenter的引用来满足视图的业务逻辑。View和 Presenter的交互是双向的,即View层可以调用Presenter的逻辑方法,Presenter也可以控制View的显示。
Presenter
Presenter作为Model和View的桥梁,负责从Model拿到数据进行处理并返回给View。但Presenter和其他两层的沟通是通过接口协议进行的,所以每个Presenter中通常会包涵一个或多个接口协议。
Model
和MVC一样,作为数据仓库只负责对APP数据进行处理。

4 listview的优化

Adapter优化convertview viewholder
1 ContentView存放于Listview的Recycle缓存中,实现的是滑出屏幕的itemView的复用,不产生新的view对象,减少了内存的重复申请以及对象回收GC,减少内存抖动,优化了listview的滑动体验。
2 ViewHolder减少了findviewbyid方法的调用。
3 加载图片,在listview快速滑动时不加载,停止滑动时加载图片

5 图片错位

引起图片错位的原因在adapter中的getView方法中异步下载图片,而该itemView在图片未下载完成已经滑出屏幕,变成了convertView重新展示在屏幕上,数据已经改变但是异步线程请求回调导致的;异步线程回调时判断url和数据中的是否一致。
6 Listview中显示不同的布局 viewType typeCount
7 下拉刷新 pullRefrensh
swipeRefrensh
上拉加载,懒加载 滑动到离底部还有n条数据时,开始请求数据
8 Spinner Galley GrideView AutoCompleteTextview
十四、Support控件
V4
1ViewPager PagerAdapter FragmentPagerAdapter
2ViewPager懒加载,Viewpager存在预加载setOffscreenPageLimit(3)
3动态配置界面。
两种 一种为根据屏幕的大小不同设置不同的界面,使用fragment设置,在xml中通过vlues值设置,主要用于手机平板的适配。
一种根据数据不同生成不同的界面 listview根据数据的不同使用不用的itemview。Activity中contentView存在一个viewGroup,根据数据创建不同的view,并将view添加到界面中。

4viewpager嵌套的解决 (http://bbs.9ria.com/thread-248286-1-1.html

引起问题的原因,viewpager互相嵌套导致左右滑动的事件传递和处理冲突导致。解决办法在子viewpager上处理滑动事件。父控件不拦截滑动事件requestDisallowInterceptTouchEvent()
ScrollView和listView嵌套,重写listview的onMeasure方法,计算listview的高度。 5 事件的处理
distouchEvent事件分发
onInterceptTouchEvent事件拦截 只有viewGroup中存在。默认不拦截事件
onTouchEvent事件处理viewgroup默认返回false,view上默认返回true
6 clipChildren 使用viewpager实现galley效果

7 Fragment碎片 碎片的作用为了更好的实现屏幕的适配。在android3.0以后提出的。

生命周期

Fragment通讯。在Fragment中调用Activity的方法,使用getActivity得到Activity
Activity设置Fragment中的view的值。直接使用fragment的对象调用
Fragment和fragment的通讯,在Activity中写调用的方法,在Fragment中调用
8 RecyclerView
Mvp设计模式 参照上方
RecyclerView.Adapter自带viewholder.三个方法 onCreate onBind getCount
三种layoutManager
LinearLayoutManager列表形式的横向纵向的listview
GrideLayoutManager 表格形式的横向纵向的GrideView
StaggeredGridLayoutManager瀑布流样式
单个的itemAnimator
9 CardView 带有边缘阴影效果的viewGroup只在androidL以上版本能展示阴影,还可以设置四个角的弧度
10 Palette 取色器 4.4以上版本通过Pallette得到颜色设置statubar的颜色得到沉浸式体验
11 NavigationDrawer 原生侧边栏 类似slidingMenu
12 FloatingActionButton 带有阴影效果
十五、5.0以上的设计
design模式
TextInputLayout 主要在输入后依然能显示edittext的hint提示
十六、动画
Animation View动画 Animator属性动画
Frame Animation逐帧动画 循环播放一组图片 类似播放gif图片
Tween Animation补间动画 透明 旋转 位移 缩放 AnimationSet
Property Animation属性动画 ValueAnimator ObjectAnimator
Objector使用PropertyValuesHolder设置多个动画
补间动画 属性动画的区别
补间动画更改的整个view的绘制方式,cpu消耗大
属性动画更改View中的一个属性,cpu消耗低

设置在viewGroup上的LayoutAnimation

十七、 自定义控件
1 Extends View
构造器(添加来自values styleable的自定义属性)
onMeasure 对View占用的空间进行测量
onDraw 对View进行绘制
onTouch 对View的事件进行处理
2 Extends SurfaceView
使用的时机,自己控制绘制的帧数
线程
3 Extends ViewGroup
onLayout 在绘制子控件时调用
measurChildren绘制子控件之前需要先测量子控件的大小
layout绘制子控件的位置
Extends EditText
4 自定义控件的优化
不在onDraw中创建对象
脏画布clipRect局部绘图
GPU一次性提交到屏幕

十八、Service

生命周期
一种为直接启动的Service
onCreate==>onStartCommond Running onDestroy
一种为绑定启动Service
onCreate==>onBind Running onUnbind==>onDestroy

在Activity中直接得到绑定的Service的对象,直接调用Service的方法。
绑定启动和直接启动的区别,直接启动的Service和启动此服务的活动没有直接联系,活动关闭时此服务不会自行关闭
绑定的启动的服务可以在启动该服务的活动中得到该服务的对象,并且能够直接调用服务的方法。在该活动关闭时,服务会自动关闭

IntentService Service 区别

IntentService自带线程,不需要重新启动一个线程去运行,并且IntentService自带一个消息队列,只有运行完上一次的方法才会运行后边传递过来的Intent。同时IntentService的线程是有应用去管理的,不需要自己去关闭其中的线程。

十九、BroadCastReceiver

1 静态注册 在Manifest.xml中注册receiver
2 动态注册 在代码中调用registerReceiver方法,在onDestory时调用unRegisterReceiver
3 系统发出的广播 电池电量低,短信,音量调节,时间调节等等
4 自己发出的
5 静态注册和动态注册区别,静态注册的情况,在应用未运行时依然可以接收到要接收的广播。动态注册只有在调用过register和unRegister之间可以接收广播

二十、ContentProvider

主要是通过getContentResolver得到resolver查询系统提供的信息:查询联系人通话记录 查询本地多媒体 

二十一、数据存储

1 SharedPrefence 存储简单数据
2 内部存储 cache getCacheDir 内部缓存 /data/data/packageName/cache
openOutput openInput 内部文件存储 /data/data/packageName/files

在sdcard的Android文件下
3 外部存储 sdcard存储 /mnt/sdcard
Environment.getExternalStorageDirectory()
得到sdcard的路径的方式
区别权限 存放文件的位置 清除数据 卸载应用后数据不会被清理
4 sqlite 路径 /data/data/packageName/database
SqliteOpenHelper
构造器 四个参数 Context factory db名称 db的版本
onCreate 调用的时机
第一次安装应用后
创建了openHelper的对象必须调用getWriteableDatabase方法后才会调用
onUpgrade 调用时机
数据库升级调用
数据库每次给表添加字段时都会清除原表的值
第一次安装应用

5 网络存储

1 应用缓存。数据缓存,保存上一次连接网络得到的数据,保存到内部存储的缓存中,在下一次打开APP时直接使用此数据,使用数据前判断过期时间,如果过期则删除。内部的cacheDir的缓存。

2 图片的二级缓存 sdcard缓存 内存缓存
连接网络返回的数据。先将图片保存到sdcard中。下次使用图片时不再重新下载,直接使用下载过的。内存缓存,android的内存机制,android应用都会占用一定的内存,图片以二进制的方式存在于内存中,如果图片使用一次后就回收,使用频率过高的话,需要在内存中反复申请新的图片的内存,需要使用lrucache保存所有使用的图片,在内存不足时先回收最先加入到lrucache中的图片,回收到足够放下新图片的内存为止。

二十二、网络

Volley okhttp

1 Volley的工作原理

其 中蓝色部分代表主线程,绿色部分代表缓存线程,橙色部分代表网络线程。我们在主线程中调用RequestQueue的add()方法来添加一条网络请求, 这条请求会先被加入到缓存队列当中,如果发现可以找到相应的缓存结果就直接读取缓存并解析,然后回调给主线程。如果在缓存中没有找到结果,则将这条请求加 入到网络请求队列中,然后处理发送HTTP请求,解析响应结果,写入缓存,并回调主线程。
Gson
json

二十三、APP优化

电量优化 闹钟 AlarmManager时钟选择适用的计时精度
Gps定位和网络定位。
网络请求,在不需要即时请求时可以将多个请求的数据一次提交,不分开

内存优化 图片的二级缓存,listview滑动过快时不加载图片;自定View 在绘制时使用clipRect 不在onDraw方法中创建对象

Apk大小优化

图片的选择 WebP 的优势体现在它具有更优的图像数据压缩算法,能带来更小的图片体积,而且拥有肉眼识别无差异的图像质量;同时具备了无损和有损的压缩模式、Alpha 透明以及动画的特性,在 JPEG 和 PNG 上的转化效果都相当优秀、稳定和统一。
网络优化 使用volley okhttp参考上方的volley原理

二十四、打包发布
数据统计
版本升级
渠道统计,渠道统计是指该APP在哪个应用市场下载的
推送
第三方登录
二十五、第三方框架 xutils ImageLoader Fresco volley okhttp eventbus pullrefresh slidingmenu 二维码扫描
二十六、友盟数据统计 推送 分享 第三方登陆
百度 数据统计 推送 分享 第三方登陆 地图 定位 百度语音
高德地图
支付宝 微信支付
环信即时通讯

apk混淆打包

(http://www.cnblogs.com/Supperlitt/p/4214949.html)

排序的方式

现在分析一下常见的排序算法的稳定性,每个都给出简单的理由。

(1)冒泡排序

    冒泡排序就是把小的元素往前调或者把大的元素往后调。比较是相邻的两个元素比较,交换也发生在这两个元素之间。所以,如果两个元素相等,我想你是不会再无聊地把他们俩交换一下的;如果两个相等的元素没有相邻,那么即使通过前面的两两交换把两个相邻起来,这时候也不会交换,所以相同元素的前后顺序并没有改变,所以冒泡排序是一种稳定排序算法。

(2)选择排序

  选择排序是给每个位置选择当前元素最小的,比如给第一个位置选择最小的,在剩余元素里面给第二个元素选择第二小的,依次类推,直到第n-1个元素,第n个元素不用选择了,因为只剩下它一个最大的元素了。那么,在一趟选择,如果当前元素比一个元素小,而该小的元素又出现在一个和当前元素相等的元素后面,那么交换后稳定性就被破坏了。比较拗口,举个例子,序列5 8 5 2 9, 我们知道第一遍选择第1个元素5会和2交换,那么原序列中2个5的相对前后顺序就被破坏了,所以选择排序不是一个稳定的排序算法。

(3)插入排序
插入排序是在一个已经有序的小序列的基础上,一次插入一个元素。当然,刚开始这个有序的小序列只有1个元素,就是第一个元素。比较是从有序序列的末尾开始,也就是想要插入的元素和已经有序的最大者开始比起,如果比它大则直接插入在其后面,否则一直往前找直到找到它该插入的位置。如果碰见一个和插入元素相等的,那么插入元素把想插入的元素放在相等元素的后面。所以,相等元素的前后顺序没有改变,从原无序序列出去的顺序就是排好序后的顺序,所以插入排序是稳定的。

(4)快速排序
快速排序有两个方向,左边的i下标一直往右走,当a[i] <= a[center_index],其中center_index是中枢元素的数组下标,一般取为数组第0个元素。而右边的j下标一直往左走,当a[j] > a[center_index]。如果i和j都走不动了,i <= j, 交换a[i]和a[j],重复上面的过程,直到i>j。 交换a[j]和a[center_index],完成一趟快速排序。在中枢元素和a[j]交换的时候,很有可能把前面的元素的稳定性打乱,比如序列为 5 3 3 4 3 8 9 10 11, 现在中枢元素5和3(第5个元素,下标从1开始计)交换就会把元素3的稳定性打乱,所以快速排序是一个不稳定的排序算法,不稳定发生在中枢元素和a[j]交换的时刻。

(5)归并排序
归并排序是把序列递归地分成短序列,递归出口是短序列只有1个元素(认为直接有序)或者2个序列(1次比较和交换),然后把各个有序的段序列合并成一个有序的长序列,不断合并直到原序列全部排好序。可以发现,在1个或2个元素时,1个元素不会交换,2个元素如果大小相等也没有人故意交换,这不会破坏稳定性。那么,在短的有序序列合并的过程中,稳定是是否受到破坏?没有,合并过程中我们可以保证如果两个当前元素相等时,我们把处在前面的序列的元素保存在结果序列的前面,这样就保证了稳定性。所以,归并排序也是稳定的排序算法。

(6)基数排序
基数排序是按照低位先排序,然后收集;再按照高位排序,然后再收集;依次类推,直到最高位。有时候有些属性是有优先级顺序的,先按低优先级排序,再按高优先级排序,最后的次序就是高优先级高的在前,高优先级相同的低优先级高的在前。基数排序基于分别排序,分别收集,所以其是稳定的排序算法。

(7)希尔排序(shell)
希尔排序是按照不同步长对元素进行插入排序,当刚开始元素很无序的时候,步长最大,所以插入排序的元素个数很少,速度很快;当元素基本有序了,步长很小,插入排序对于有序的序列效率很高。所以,希尔排序的时间复杂度会比o(n^2)好一些。由于多次插入排序,我们知道一次插入排序是稳定的,不会改变相同元素的相对顺序,但在不同的插入排序过程中,相同的元素可能在各自的插入排序中移动,最后其稳定性就会被打乱,所以shell排序是不稳定的。

(8)堆排序
我们知道堆的结构是节点i的孩子为2*i和2*i+1节点,大顶堆要求父节点大于等于其2个子节点,小顶堆要求父节点小于等于其2个子节点。在一个长为n的序列,堆排序的过程是从第n/2开始和其子节点共3个值选择最大(大顶堆)或者最小(小顶堆),这3个元素之间的选择当然不会破坏稳定性。但当为n/2-1, n/2-2, …1这些个父节点选择元素时,就会破坏稳定性。有可能第n/2个父节点交换把后面一个元素交换过去了,而第n/2-1个父节点把后面一个相同的元素没有交换,那么这2个相同的元素之间的稳定性就被破坏了。所以,堆排序不是稳定的排序算法

Object

1.getClass
public final Class? extends Object> getClass()
返回一个对象的运行时类。
2.hashCode
public int hashCode()
返回该对象的哈希码值。
3.Equals方法
Object类中的equals方法用于检测一个对象是否等于另外一个对象。在Object类中,这个方法将判断两个对象是否具有相同的引用。
4.toString
public String toString()
返回该对象的字符串表示。
5.notify
public final void notify()
唤醒在此对象监视器上等待的单个线程。
6.notifyAll
public final void notifyAll()
唤醒在此对象监视器上等待的所有线程。线程通过调用其中一个 wait 方法,在对象的监视器上等待。
7.wait
public final void wait(long timeout)
throws InterruptedException
导致当前的线程等待,直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者超过指定的时间量。
当前的线程必须拥有此对象监视器。

此方法导致当前线程(称之为 T)将其自身放置在对象的等待集中,然后放弃此对象上的所有同步要求。出于线程调度目的,线程 T 被禁用,且处于休眠状态,直到发生以下四种情况之一:

其他某个线程调用此对象的 notify 方法,并且线程 T 碰巧被任选为被唤醒的线程。
其他某个线程调用此对象的 notifyAll 方法。
其他某个线程中断线程 T。
已经到达指定的实际时间。但是,如果 timeout 为零,则不考虑实际时间,该线程将一直等待,直到获得通知。

内存溢出,程序崩溃怎么办。比如下载的图片太大?

尽量不要使用setImageBitmap或setImageResource或BitmapFactory.decodeResource来设置一张大图,
因为这些函数在完成decode后,最终都是通过java层的createBitmap来完成的,需要消耗更多内存。

因此,改用先通过BitmapFactory.decodeStream方法,创建出一个bitmap,再将其设为ImageView的 source,
decodeStream最大的秘密在于其直接调用JNI>>nativeDecodeAsset()来完成decode,
无需再使用java层的createBitmap,从而节省了java层的空间。
如果在读取时加上图片的Config参数,可以跟有效减少加载的内存,从而跟有效阻止抛out of Memory异常
另外,decodeStream直接拿的图片来读取字节码了, 不会根据机器的各种分辨率来自动适应,
使用了decodeStream之后,需要在hdpi和mdpi,ldpi中配置相应的图片资源,
否则在不同分辨率机器上都是同样大小(像素点数量),显示出来的大小就不对了。

另外,以下方式也大有帮助:
1. InputStream is = this.getResources().openRawResource(R.drawable.pic1);
BitmapFactory.Options options=new BitmapFactory.Options();
options.inJustDecodeBounds = false;
options.inSampleSize = 10; //width,hight设为原来的十分一
Bitmap btp =BitmapFactory.decodeStream(is,null,options);
2. if(!bmp.isRecycle() ){
bmp.recycle() //回收图片所占的内存
system.gc() //提醒系统及时回收
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值