首页 文章 精选 留言 我的

精选列表

搜索[面试],共4913篇文章
优秀的个人博客,低调大师

java 面试题分析

题: 定义两个 Integer 对象传递给一个方法, 方法执行后两个 Integer 的值需要互相转换 public static void practise(MyConsumer<Integer> consumer) { Integer value1 = 1; Integer value2 = 2; System.out.println("start: value1=" + value1 + ", value2=" + value2); consumer.accept(value1, value2); System.out.println("end: value1=" + value1 + ", value2=" + value2); } @FunctionalInterface public interface MyConsumer<T> { void accept (T value1, T value2); } 编程方式一: 传值与传引用的区别 practise((value1, value2) -> { Integer temp = value1; value1 = value2; value2 = temp; return; }); 输入结果: start: value1=1, value2=2 end: value1=1, value2=2 编程方式二: Integer 在 -127 ~ 128 之间的缓存 practise((value1, value2) -> { try { Field declaredField = Integer.class.getDeclaredField("value"); declaredField.setAccessible(true); Integer intValue = value1.intValue(); declaredField.set(value1, value2); declaredField.set(value2, intValue); } catch (Exception e) {} return; }); 输出结果: start: value1=1, value2=2 end: value1=2, value2=2 编程方式三: 清空缓存 practise((value1, value2) -> { try { Field declaredField = Integer.class.getDeclaredField("value"); declaredField.setAccessible(true); Integer intValue = new Integer(value1.intValue()); declaredField.set(value1, value2); declaredField.set(value2, intValue); } catch (Exception e) {} return; }); 输出结果: start: value1=1, value2=2 end: value1=2, value2=1

优秀的个人博客,低调大师

算法面试题(四)

1. 问题:有一对兔子,从出生第3个月起每个月都生一对兔子,小兔子长到第三个月后每个月也生一对兔子,假如兔子都不死,问每个月兔子的总数是多少?这个一个菲波拉契数列问题。 package test; /** * @author cz * @date 2018年7月29日 */ public class Test10 { //月 1 2 3 4 5 6 7 8 9 10 11 12 //对 1 1 2 3 5 8 13 21 34 55 89 144 public static void main(String[] args) { System.out.println("第1个月:"+1+"对"); System.out.println("第2个月:"+1+"对"); //记录月 int M=24; // int f1=1,f2=1; int f; for(int i=3;i<=M;i++){ f=f2; f2=f1+f2; f1=f; System.out.println("第"+i+"个月:"+f2+"对"); } } } 2.已知有一个数列,f(0)=1,f(1)=4,f(n+2)=2*f(n+1)+f(n);求f(10).(提示:递归只能往已知方向走) package test; /** * @author cz * @date 2018年7月29日 */ public class Test11 { public static void main(String[] args) { System.out.println(func(10)); } public static int func(int n){ if(n==0) return 1; else if(n==1) return 4; else{ return 2*func(n-1) + func(n-2); //return func(n+2)-2*func(n+1); } } } 3.求1-10之间整数的阶乘 package test; import java.util.HashMap; public class Test12 { public static void main(String[] args) { for(long i=1;i<=10;i++){ System.out.println(i+"!="+fact(i)); } } //阶乘方法 public static long fact(long n){ if(n==0 || n==1) return 1; else if(n<0) return 1; else { return n*fact(n-1); } } } 4.输入一个只包含加减乖除和括号的合法表达式,求表达式的值。其中除表示整除。 输入格式 输入一行,包含一个表达式。 输出格式 输出这个表达式的值。 样例输入 1-2+3*(4-5) 样例输出 -4 数据规模和约定 表达式长度不超过100,表达式运算合法且运算过程都在int内进行。 解题思路: 1,初始化两个栈:运算符栈S1和储存中间结果的栈S2; 2,从左至右扫描中缀表达式; 3,遇到操作数时,将其压入S2,这里由于运算数可能大于10,所以如果数字后面一个符号是运算符,则将‘#’入S2栈充当分割线; 4, 遇到运算符时有三种情况: (4-1) 三种情况下直接入S1栈①S1为空②运算符为‘(’③运算符优先级比S1栈顶运算符的高; (4-2)如果右括号“)”,则依次弹出S1栈顶的运算符,并压入S2,直到遇到左括号为止,此时将这一对括号丢弃; (4-3) 若运算符优先级小于或等于S1栈顶运算符的优先级,则依次弹出S1栈顶元素,直到运算符的优先级大于S1栈顶运算符优先级; 5, 重复步骤(2)至(5),直到表达式的最右边; 6,将S1中剩余的运算符依次弹出并压入S2; 7,依次弹出S2中的元素并输出,结果的逆序即为中缀表达式对应的后缀表达式 解题 import java.util.Scanner; import java.util.Stack; public class Main{ public static void main(String[] args) { // TODO Auto-generated method stub Scanner scanner = new Scanner(System.in); Stack<Integer> nums = new Stack<Integer>(); // 保存数字 Stack<Character> opes = new Stack<Character>(); // 保存操作符 String string = scanner.nextLine(); int n = 0; // 保存每一个数字 char[] cs = string.toCharArray(); for (int i = 0; i < cs.length; i++) { char temp = cs[i]; if (Character.isDigit(cs[i])) { n = 10 * n + Integer.parseInt(String.valueOf(cs[i])); // 大于10的数字保存 } else { if (n != 0) { nums.push(n); n = 0; } if (temp == '(') { opes.push(temp); } else if (temp == ')') { while (opes.peek() != '(') { // 括号里面运算完 int t = cal(nums.pop(), nums.pop(), opes.pop()); nums.push(t); } opes.pop(); } else if (isType(temp) > 0) { if (opes.isEmpty()) { // 栈为空直接入栈 opes.push(temp); } else { // 若栈顶元素优先级大于或等于要入栈的元素,将栈顶元素弹出并计算,然后入栈 if (isType(opes.peek()) >= isType(temp)) { int t = cal(nums.pop(), nums.pop(), opes.pop()); nums.push(t); } opes.push(temp); } } } } // 最后一个字符若是数字,未入栈 if (n != 0) { nums.push(n); } while (!opes.isEmpty()) { int t = cal(nums.pop(), nums.pop(), opes.pop()); nums.push(t); } System.out.println(nums.pop()); } // 返回的是运算符的优先级,数字和()不需要考虑 public static int isType(char c) { if (c == '+' || c == '-') { return 1; } else if (c == '*' || c == '/') { return 2; } else { return 0; } } // 运算次序是反的,跟入栈出栈次序有关 public static int cal(int m, int n, char c) { int sum = -987654321; if (c == '+') { sum = n + m; } else if (c == '-') { sum = n - m; } else if (c == '*') { sum = n * m; } else if (c == '/') { sum = n / m; } return sum; } } 5.用两个栈实现一个队列,完成队列的push和pop,队列中的元素为int类型。 import java.util.Stack; //使用栈记得引用java.util,Stack包 public class Solution { Stack<Integer> stack1 = new Stack<Integer>(); Stack<Integer> stack2 = new Stack<Integer>(); //入栈函数 public void push(int num) { stack1.push(num); //要往栈中压入什么就直接用栈的push方法就好了 } //出栈函数 public int pop() { Integer re=null; if(!stack2.empty()){ // 如果栈2不是空的,那么把最上面那个取出来 re=stack2.pop(); }else{ //如果栈2是空的,就把栈1里的数一个个取出来,放到栈2里 while(!stack1.empty()){ re=stack1.pop(); stack2.push(re); } //栈2里有数之后,再次把里面的数取出来 if(!stack2.empty()){ re=stack2.pop(); } } return re; } } 原文发布时间为:2018-09-18 本文作者: IT技术之道 本文来自云栖社区合作伙伴“ IT技术之道”,了解相关信息可以关注“ IT技术之道”。

优秀的个人博客,低调大师

常见List面试问题

List的相关文章,没有太多想写的,早先的时候有提到过两篇 ArrayList VS LinkedList ArrayList扩容原理 除此之外还有一些经常被问到的问题,我从Hollis的知识星期收集一下,用到这里,供一起学习 问题 Java 中 Set 与 List 有什么不同? 相同点:都是继承Collection的接口,都是用来存储一组相同类型的元素 不同点: List有序存储,元素可重复 Set无序存储,元素不可重复 注意:Set在插入时是要有一定的方法来判断元素是否重复的,这个方法很重要,决定了set种可以保存那些元素,Java中的HashSet使用的是HashMap来存储,弄明白HashMap原理之后就明白HashSet的原理了。 HashMap初探 HashMap实现原理 HashSet VS TreeSet Java中的List有几种实现,各有什么不同? Vector,ArrayList,LinkedList 还差Vector没有说到,Vector实现方式与ArrayList类似,不过在方法上加了Synchronized关键字来保证现场安全。 ArrayList 是一个可改变大小的数组.当更多的元素加入到ArrayList中时,其大小将会动态地增长.内部的元素可以直接通过get与set方法进行访问,因为ArrayList本质上就是一个数组. LinkedList 是一个双链表,在添加和删除元素时具有比ArrayList更好的性能.但在get与set方面弱于ArrayList. 当然,这些对比都是指数据量很大或者操作很频繁的情况下的对比,如果数据和运算量很小,那么对比将失去意义. Vector 和ArrayList类似,但属于强同步类。如果你的程序本身是线程安全的(thread-safe,没有在多个线程之间共享同一个集合/对象),那么使用ArrayList是更好的选择。 Vector和ArrayList在更多元素添加进来时会请求更大的空间。Vector每次请求其大小的双倍空间,而ArrayList每次对size增长50%. 而 LinkedList 还实现了 Queue 接口,该接口比List提供了更多的方法,包括 offer(),peek(),poll()等. 注意: 默认情况下ArrayList的初始容量非常小,所以如果可以预估数据量的话,分配一个较大的初始值属于最佳实践,这样可以减少调整大小的开销。 什么是fail-fast,什么是fail-safe,有什么区别吗? fail-fast字面意思,快速失败,也就是当集合类遇到数据问题时时立刻抛出异常,常规的集合类都是如此,在多线程同时操作时会立刻抛出concurrentmodificationexception fail-safe当集合类在多线程环境下处理的时候,遇到问题时,不会抛出异常,而是继续执行下去。 以上是个人理解。 java中fail-fast 和 fail-safe的区别 通过Array.asList获得的List有何特点,使用时应该注意什么? Array.asList获取的列表,使用的是适配器模式,其List是Array内部的实现,内部的数据指向的还是数组,并且不支持插入,删除操作。 解:1. asList 得到的只是一个 Arrays 的内部类,一个原来数组的视图 List,因此如果对它进行增删操作会报错 用 ArrayList 的构造器可以将其转变成真正的 ArrayList 最后 以上是常问道的关于List相关的问题,一次小小的总结。

优秀的个人博客,低调大师

Android面试之Java基础

一、java面向对象的三大特性与含义 1、继承:从已有的类得到继承信息创建新类的过程,继承让变化中的软件系统有了一定的延续性,同时继承也是封装程序的可变因素的重要手段。 2、封装:通常认为封装是把数据和操作数据的方法绑定起来,对数据的访问只能通过已经定义的接口。面向对象的本质就是将现实世界描绘成一系列完全自制、封闭的对象。可以说,封装就是隐藏一切可隐藏的东西,只向外界提供简单的编程接口; 3、多态:允许不同子类型的对象对同一消息作出不同的响应。简单说就是用同样的对象引用调用同样的方法但是做了不同的事情。 4、实现多态需要做的两件事:①、方法重写;②、对象造型 二、java多态 1、多态定义:允许不同类的对象对同一消息作出响应,即同一消息可以根据发送对象的不同而表现出多种不同的行为方式。 2、多态的作用:消除类型间的耦合关系。 3、实现多态的技术:动态绑定 4、多态存在的必要条件:①有继承;②有重写;③父类引用指向子类对象。 5、多态的好处:①可替换性、②可扩充性、③接口性、④灵活性、⑤简化性。 6、多态的实现方式:接口实现、继承父类进行方法重写、同一个类内进行方法重载。 三、Java中的SoftReference是什么? 1、Java 中的 SoftReference 即对象的软引用。如果一个对象具有软引用,内存空间足够,垃圾回收器就不会回收它;如果内存空间不足了,就会回收这些对象的内存。只要垃圾回收器没有回收它,该对象就可以被程序使用。软引用可用来实现内存敏感的高速缓存。使用软引用能防止内存泄露,增强程序的健壮性。 2、SoftReference的特点:它的一个实例保存对一个Java对象的软引用,该软引用的存在不妨碍垃圾收集线程对该Java对象的回收。也就是说,一旦SoftReference保存了一个Java对象的软引用后,在垃圾线程对这个Java对象回收前,SoftReference类所提供的get()方法返回Java对象的强引用。但是,一旦垃圾线程回收该Java对象之后,get()方法将返回null。 四、abstract关键字 1、abstract可以修饰类、方法 2、如果一个类被abstract修饰,此类必须被继承使用,此类不可以生成对象,但是可以声明。 3、abstract可以 将子类的共性最大限度的抽取出来放在父类,以提高代码的简洁性。 4、abstract修饰方法时,方法为抽象方法,该方法不需要进行实现,实现留给子类,子类覆盖该方法之后才能生效。 5、abstract不能与static、final放在一起否则会出现错误 五、重写和重载 1、重写:如果子类中定义的某个方法与其父类有相同的名称和参数,则该方法被重写了。 2、重载:如果一个类内有多个重名的方法,它们或有不同的参数个数、或有不同的参数类型、或有不同的参数次序,则称为重载。 3、重载的规则:必须改变参数列表、可以改变返回类型、可以改变访问修饰符、可以声明新的或更广的检查异常、能够在同一个类中或者在一个子类中被重载、无法通过返回值类型来判断方法是否重载。 4、重写的规则:参数列表、返回值类型必须相同,访问权限不能低于父类的方法,被final修饰的方法不能被重写,static修饰的方法不能被重写但是可以再次声明,构造方法不能被重写,重写方法不能抛出更广泛的强制异常,访问权限不能下降。 六、Java中如何定义常量 1、接口中常量默认为static final; 2、Java 5.0 中引入类Enum类型; 3、在普通类中使用static final修饰的变量; 七、abstract、interface、final、static总结 abstract 1、只要含有抽象方法的类必须声明为抽象类; 2、抽象类可以有具体的实现方法; 3、抽象类内可以没有抽象方法; 4、抽象方法必须被子类实现,或者子类也是抽象的; 5、抽象类不可以被实例化,但是可以被声明; 6、若使用抽象类内部的方法,则必须有一个子类继承这个抽象类,并且实现抽象方法,通过子类实例化去调用; interface 1、接口内成员变量必须定义初始化; 2、接口内的成员方法只能是方法原型,不能有方法体; 3、接口内的成员变量和方法只能是public的; 4、实现接口的类必须全部实现接口的方法; final 1、可以修饰成员变量、非抽象类、非抽象类成员方法、方法参数; 2、final方法不能被子类重写,但是可以被继承; 3、final类不可以被继承,final类内部的方法也无法被继承; 4、final修饰的变量只能被赋值一次,赋值之后不能被修改; 5、final不能修饰构造方法; 6、final的参数:只能被使用,不能修改该参数的值 static 1、可以修饰成员变量和成员方法,但是不能修饰类(静态内部类除外)以及构造方法; 2、static修饰的成员变量和成员方法独立于这个类,被类的所有实例共享; 3、static修饰的类和成员方法可以通过类名直接访问,也可以通过实例来访问; 4、private修饰的static变量和static方法只能在声明的本类方法及静态块内访问,但不能使用this方法,因为this是非静态变量。 static+final同时修饰 1、该变量或者方法可以简单理解为全局常量; 2、对于变量一但给值就不可以修改,可以通过类名进行访问; 3、对于方法,表示不可覆盖,可以通过类名直接访问; switch是否可以使用string来作为参数? Java 5之后switch可以引用enum、byte、short、char、int作为参数 Java 7 之后引入string 八、Object有哪些公用方法 1、clone方法 保护方法,实现对象的浅复制,只有实现了Cloneable接口才可以调用该方法,否则会抛出CloneNotSupportException异常。 2、getClass()方法 final方法,获得运行时类型 3、toString()方法 不用多说了( ̄ ̄)~* 4、finalize方法 释放资源使用,很少使用; 5、equals()方法 只有在Object中equals方法和==是一样,其他时候两者不一样。 6、hashCode()方法 该方法用于哈希值的查找,可以减少equals方法的使用,提高代码运行效率。 7、wait()方法 wait方法就是使当前线程等待该对象的锁,当前线程必须是该对象的拥有者,也就是具有该对象的锁。wait方法一直等待,直到获得锁或者被中断。 调用该方法后当前线程进入睡眠状态,直到发生以下事件 ①、其他线程调用了该对象的notify方法; ②、其他线程调用该对象的notifyAll方法; ③、其他线程调用了interrupt方法中断该线程; ④、时间间隔到了。 八、int和integer的区别 1、int是基本数据类型 2、integer是int的封装类 3、int和integer都可以表示某一个数值 4、int和integer不能够互用,因为他们两种不同的数据类型 九、string是否可以被继承 不可以,因为String为final类 十、常量 final String str=“ab”可不可以编程“abc”,为什么? 不可以,因为使用final修饰的变量不可改变 十一、String、StringBuffer、StringBuilder之间的区别 三者执行效率为:StringBuilder>StringBuffer>String String字符串为常量,不可改变; StringBuilder字符串变量(非线程安全) StringBuffer字符串变量(线程安全) String类型进行改变的时候其实等同于生成 一个新的String对象,然后指针指向新的String对象。会导致jvm的gc开始工作导致速度变慢; StringBuffer一个类似于String的字符串缓冲区,但是不能修改。但是可以通过某些方法来改变该序列的长度和内容。 StringBuffer上主要操作的是append方法和insert方法,append方法是将任意类型的数据转换成字符串添加到缓存区末端,而insert方法是制定的添加字符串。 String s=new Sting(“abc”);new了几个对象? 两个 String源码分析 String对象是不可变类型,返回类型为String的String方法每次返回的都是新的String对象,除了某些方法的某些特定条件返回自身。 String对象的三种比较方式: 1、==内存比较:直接对比两个引用所指向的内存值,精确简洁直接明了。 2、equals字符串值比较:比较两个引用所指对象字面值是否相等。 3、hashCode字符串数值化比较:将字符串数值化。两个引用的hashCode相同,不保证内存一定相同,不保证字面值一定相同。 十二、内部类 静态内部类和非静态内部类的区别 1、静态内部类不持有外部类的引用,非静态内部类持有外部类的引用 2、静态内部类可以有静态成员,非静态内部类不能持有静态成员; 3、静态内部类只能访问外部类的静态成员和静态方法,非静态内部类可以访问外部类的所有成员和方法; 4、实例化一个静态内部类不需要外部类的实例;实例化一个非静态内部类需要通过外部类的实例生成内部类的实例; 5、调用静态内部类的方法或变量可以通过类名直接调用。 为什么内部类拥有外部类的所有元素的访问权? 内部类对象只能在与其外部类对象关联的情况下才能被创建,构建内部类需要一个外部类的引用,内部类正是通过这个引用去访问外部类的。 内部类的种类 成员内部类、方法内部类、匿名内部类、静态内部类 内部类的作用 1、内部类可以 用多个实例,每个实例都有自己的状态信息,并且与其他外围对象的信息相互独立; 2、单个外围类中,可以让多个内部类以不同的方式实现同一个接口,或者继承同一个类。 3、创建内部类对象的时刻并不依赖于外围类对象的创建; 4、内部类是一个独立的实体; 5、内部类提供了更好的封装,除了外围类,其他类都不能进行访问 静态内部类、内部类、匿名内部类,为什么内部类会持有外部类的引用?持有的引用是this?还是其它? 因为内部类的产生依赖于外部类,持有的引用是“类名.this”; 十三、抽象类和接口 抽象类的总结 1、抽象类不能被实例化 2、抽象类内部不一定包含抽象方法,有抽象方法的类一定是抽象类 3、抽象类内部的方法只是声明,不包含方法体,就是不给出具体的实现也就是方法的具体功能; 4、构造方法、类方法不能声明为抽象方法 5、抽象类的子类必须给出抽象类中抽象方法的具体实现,除非这类也是抽象类。 接口与类的区别 接口不能用于实例化对象; 接口没有构造方法; 接口内的方法必须是抽象方法; 接口不能包含成员变量,除非是static 和 final修饰的; 接口不是被类继承而是被类实现; 接口支持多重继承 接口特性 1、接口中的每一个方法都是隐式抽象的,接口中的方法会被隐式的指定为 public abstract; 2、接口内可以含有变量,但是接口中的变量会被隐式的指定为public static final 变量; 3、接口中的方法是不能在接口中实现的,只能由实现接口的类来实现接口内部的方法; 抽象类与接口的区别 1、抽象类内部的方法可以有方法体,但是接口内部的方法不行; 2、抽象类中的成员变量可以是各种类型的,而接口的成员变量只能是public static final类型的; 3、接口中不能有静态代码块以及静态方法,而抽象类内可以有静态代码块和静态方法,java8新特性允许接口内存在静态方法; 4、一个类只能继承一个抽象类,而一个类可以实现多个接口; 5、接口中不能有构造函数和main方法;抽象类内可以有; 6、接口是被实现;抽象类类是被继承。 接口的意义 1、提供一个规范,要求类必须实现指定的方法; 2、解决Java中的单继承问题,可以用接口来实现多继承的功能,简单化多重继承中继承树的复杂程度; 3、增强程序的扩展性。 抽象类的意义 为其子类提供一个公共的类型,封装子类中的重复内容,定义抽象方法,子类虽然有不同的实现,但是定义是一致的。 十四、接口是否可继承接口? 抽象类是否可实现(implements)接口? 抽象类是否可继承实体类(concreteclass)? 1、接口可以继承接口,使用关键字extends 2、抽象类可以实现接口。AbstractCollection类就实现了Collection接口; 3、抽象类可以继承实体类。 十五、abstract的方法是否可以同时是static,是否可同时是native,是否可同时是final? 都不行 abstract的方法不可以是static的,因为抽象的方法是要被子类实现的,而static与子类没有关系! native方法表示该方法要用另外一种依赖平台的编辑语言实现的,不存在者被子类实现的问题,所以,他也不能是抽象的,不能与abstract混用。 十六、final关键字 1、final修饰的类不能被继承,final类内部的方法都被隐式的指定为final方法; 2、final修饰的方法的原因:明确禁止该方法在子类中被覆盖; 3、修饰变量:①、基本数据类型的变量,数值一旦被初始化便不能更改;②、引用类型变量,初始化之后不能再让其指向另一个对象 4、final修饰的引用形变量其指向的对象内容可变。 十七、finally final finalize的作用? final用于声明属性、方法和类; finally是异常处理语句结构的一部分,表示总是执行; finalize是Object类的一个方法。 十八、Collection与Collections的区别 Collection是一个接口,它是Set、List等容器的父接口; Collections是一个工具类,提供了一系列的静态方法来辅助容器操作,这些方法包括对容器的搜索、排序、线程安全化等 十九、Set和List的区别 1、Set接口存储的是无序的、不重复的数据;List接口存储的是有序的、可以重复的数据; 2、Set检索效率低,删除和插入效率高、删除和插入不会引起元素位置变化,实现类有HashSet、TreeSet。 List检索效率高、插入和删除效率低,因为引起其他元素的位置变化,实现类有ArrayList、LinkdList、Vector。 二十、hashCode方法的作用 hashCode方法主要作用是为了配合基于散列的集合一起正常的运行,这样的散列的集合包括hashSet、HashMap、HashTable。 why?考虑到一种情况就是当向集合内部插入对象时,不允许有重复对象。 当向集合内部添加新对象时,首先调用对象的hashCode方法得到对象的哈希值,实际上在HashMap的具体实现中会用到一个table保存已经存进去的对象的hashCode,如果table内没有该哈希值,它就可以直接存进去不用进行比较了,如果存在则调用它的equals方法与新元素进行比较如果相同的话就不存了,不同的话存进去。这样的话就大大降低了equals方法的使用,提高了程序的运行效率。 如果equals方法得到的结果为true,则两个对象的hashcode值必定相等; 如果equals方法得到的结果为false,则两个对象的hashcode值不一定不同; 如果两个对象的hashcode值不等,则equals方法得到的结果必定为false; 如果两个对象的hashcode值相等,则equals方法得到的结果未知。 多线程环境中安全使用集合API 在集合API中最初设计的Vector和HashTable是多线程安全的。例如Vector,用来添加和删除元素的方法是同步的,如果只有一个线程与其进行交互,那么要求获取和释放对象锁是一种浪费,另外在不必要的时候滥用同步化也可能带来死锁现象。因此集合的本质上是非多线程安全的,当与多线程交互时,为了使它多线程安全,必须采取额外措施。 HashMap的实现原理 HashMap底层就是一个数组结构,数组中的每一项又是一个链表。当新建一个HashMap的时候就会初始化一个数组。 二十一、容器之间的区别 HashMap与HashTable的区别 1、继承不同 HashMap继承自Dictionary 、HashTable继承自AbstractMap 2、HashTable中的方法是同步的,HashMap的方法不是同步的; 3、HashTable内的key和value都不允许出现null,HashMap中的null可以作为键,这样的键只能有一个;可以有一个或者是多个键对应的值是null; 4、两个遍历方式不同 5、HashTable直接使用对象的哈希值、HashMap重新计算哈希值; ArrayMap和HashMap的区别 1、存储方式不同。ArrayMap使用的两个数组进行存储,HashMap使用链表进行存储; 2、扩容处理方法不一样。ArrayMap使用System.arraycopy()copy数组,而 HashMap 使用 new HashMapEntry 重新创建数组。 3、ArrayMap 提供了数组收缩的功能,在clear或remove后,会重新收缩数组,节省空间。 4、ArrayMap 采用二分法查找。 ArrayList Vector LinkedList 三者的区别 1、三者都实现了List 接口;但 LinkedList 还实现了 Queue 接口。 2、ArrayList 和 Vector 使用数组存储数据;LinkedList 使用双向链表存储数据。 3、ArrayList 和 LinkedList 是非线程安全的;Vector 是线程安全的。 4、ArrayList 数据增长时空间增长50%;而 Vector 是增长1倍; 5、LinkedList 在添加、删除元素时具有更好的性能,但读取性能要低一些。 6、LinkedList 与 ArrayList 最大的区别是 LinkedList 更加灵活,并且部分方法的效率比 ArrayList 对应方法的效率要高很多,对于数据频繁出入的情况下,并且要求操作要足够灵活,建议使用 LinkedList;对于数组变动不大,主要是用来查询的情况下,可以使用 ArrayList。 二十二、内存相关知识点 Java程序运行时的内存分配策略有三种,分别是静态分配、栈式分配和堆式分配。对应的就是静态存储区、栈区、堆区。 1、静态存储区:主要存放静态数据、全局static数据和常量。这块内存在程序编译时已经分配确定,并且在程序整个运行期间都会存在; 2、栈区:当方法执行时,方法体内部的局部变量都在栈上创建,并在方法执行结束时这些局部变量持有的内存将会自动释放 3、堆区:又称之为动态内存分配,通常指程序运行时直接new出来的内存,也就是对象的实例。这部分内存不使用时会由垃圾回收器进行回收 栈与堆的区别 栈:在方法体内定义的一些基本类型变量和对象引用的变量都是在方法的栈内存中进行分配的。 堆:用来存放所有由new创建的对象和数组。在堆中分配的内存,将由Java垃圾回收器自动管理。当在堆中产生一个数组或者对象后,还可以在栈中定义一个特殊的变量,这个变量取值等于数组或者对象在堆内存中的首地址,这个特殊变量就是引用变量。可以通过引用变量来访问堆中的对象或者是数组 结论: 1、局部变量的基本数据类型和引用存储于栈中,引用对象的实体存储于堆中。 2、成员变量存储于堆中。因为他们属于类,类对象终究是要被new出来使用的。 3、栈存取速度仅次于寄存器,存储效率比堆高,可以共享存储数据,但是其中数据大小和生存期必须在运行前确定。 4、堆是运行时可动态分配的数据区,从速度看比栈慢,堆里面的数据不共享大小和生存期都可以在运行时再确定。 Java如何管理内存? Java的内存管理就是对象的内存分配和释放问题。在Java中程序员通过new来为每个对象在堆中申请内存空间,所有的对象都在堆中分配空间。对象的释放由GC决定和执行,由于内存分配和释放由两条线来完成简化了程序员的工作,但是增加了jvm的工作。这也是Java运行速度较慢的原因之一。因为GC为了能够正确释放对象,GC必须监控每一个对象的运行状态,监视对象的目的是为了更加准确及时的释放对象,而释放对象的原则是该对象不被引用。 为了更好理解 GC 的工作原理,我们可以将对象考虑为有向图的顶点,将引用关系考虑为图的有向边,有向边从引用者指向被引对象。另外,每个线程对象可以作为一个图的起始顶点,例如大多程序从 main 进程开始执行,那么该图就是以 main 进程顶点开始的一棵根树。在这个有向图中,根顶点可达的对象都是有效对象,GC将不回收这些对象。如果某个对象 (连通子图)与这个根顶点不可达(注意,该图为有向图),那么我们认为这个(这些)对象不再被引用,可以被 GC 回收。 Java使用有向图的方式进行内存管理,可以消除引用循环的问题,例如有三个对象,相互引用,只要它们和根进程不可达的,那么GC也是可以回收它们的。这种方式的优点是管理内存的精度很高,但是效率较低。另外一种常用的内存管理技术是使用计数器,例如COM模型采用计数器方式管理构件,它与有向图相比,精度行低(很难处理循环引用的问题),但执行效率很高。 什么是Java内存泄漏? 这些对象具有如下两个特点。①、这些对象是可达的即在有向图内存在通路与其相连;②、这些对象是无用的,即以后程序不会再使用这些对象。如果对象满足这两个条件,那么我们就可以认为这些对象为Java中的内存泄漏,但是这些对象不会被GC回收,然而占用内存。 Java的内存回收机制 所有的编程语言的内存分配方式都需要返回分配内存的真实地址,也就是返回一个指针到内存块的首地址,Java中对象是采用new或者反射的方式创建的,这些对象的创建都是在堆中分配的,所有对象的回收都是由Java虚拟机通过垃圾回收机制完成的。GC为了能够准确的释放对象会监控每一个对象的运行状况(申请、引用、被引用、赋值),Java使用由向意图的方法进行管理内存,实时监控对象是否可以到达,如果不可到达则进行回收。这样也可以消除引用循环的问题。 判断内存空间是否符合垃圾回收标准? ①、对象被赋予了空值null,再也没有调用过; ②、给对象赋予了新值,这样重新分配了内存空间; Java内存泄漏引起的原因 内存泄漏的定义:无用的对象持续占有内存或无用对象的内存得不到及时释放,从而导致内存空间的浪费。严重的内存泄漏会导致内存溢出(OOM)。 内存泄漏的根本原因: 长生命周期的对象持有短生命周期对象的引用就很可能发生内泄漏。 具体导致内存泄漏的原因: 1、静态集合引起的内存泄漏 HashMap、Vector等的使用容易出现内存泄漏,这些静态变量的生命周期和应用程序一致,他们所引用的所有的对象Object也不能被释放,因为他们也将一直被Vector等引用着。 解决方法:及时将集合对象设置为null。 2、监听器 在释放对象的时候忘记删除对象的监听器,从而增加了内存泄漏的机会。 解决方法:及时删除监听器 3、各种连接 比如数据库连接(dataSourse.getConnection()),网络连接(socket)和io连接。 解决方法:显示调用close()方法,否则是不会自动被GC回收的。 4、内部类和外部模块的引用 解决方法:细节,时刻提醒提供相应方法去除引用 5、单例模式 不正确使用单例模式导致。单例对象在初始化后将在jvm的整个生命周期中存在,如果单例对象持有外部类的引用,那么这个对象将不能被JVM正常回收导致内存泄漏。 Java内存回收机制,GC 垃圾回收机制,垃圾回收的优点和原理,并说出3种回收机制。 优点: 1、Java语言显著的特点就是引入了垃圾回收机制,它使程序员在编写程序时不再考虑内存管理问题,直接解放了程序员的大脑; 2、由于有了垃圾回收机制,Java对象不再有“作用域的概念”,只有引用对象才有“作用域”的概念; 3、垃圾回收机制有效的防止了内存泄漏,可以有效的使用空闲的内存; 4、垃圾回收器通常作为一个单独的低级别的线程运行,在不可预知的情况下进行对内存堆中的已经死亡的或者长时间没有用过的对象进行清除和回收。 5、程序员实时的对某个对象调用垃圾回收器进行垃圾回收。 垃圾回收机制:分带复制垃圾回收、标记垃圾回收、增量垃圾回收 垃圾回收算法 1、引用计数算法:缺点是无法处理循环引用问题 2、标记-清除算法:标记所有从根节点开始的可达的对象。缺点是会造成空间不连续,导致不容易分配内存 3、标记-压缩算法:标记清除算法的升级版,原理:清除未标记对象时还将所有的存活对象压缩到内存的另一端,之后清理边界所有的空间既避免碎片产生,又不需要两块同样大小的内存块。适用于老年代。 4、复制算法:将内存空间分为两块,每次将正在使用的内存中存活对象复制到未使用的内存块中,之后清除正在使用的内存块。算法效率高,但是代价是系统内存折半。适用于新生代。 5、分代 Java虚拟机的特性 Java语言的一个非常重要的特性就是与平台无关性,而Java虚拟机是实现这一特性的关键。一般的高级语言在不同的平台上运行,至少需要编译成不同的目标代码。然而引入Java语言虚拟机之后,Java在不同平台运行的时不需要重新编译,Java语言使运行时Java虚拟机屏蔽了与具体平台相关的信息,使得Java语言编译程序只需生成在Java虚拟机上运行的目标代码(字节码),就可以在多种平台上不加修改地运行。Java虚拟机在执行字节码时,把字节码解释成具体平台上的机器指令执行。 哪些情况下的对象会被垃圾回收器回收掉 Java的回收机制最基本的做法就是分代回收。内存中的区域被划分为不同的世代,对象根据其存活时间被保存在在不同的世代内。一般被分为三个世代分别为:年轻、年老、永久。内存分配是发生在年轻世代内,对于不同的世代可以才用不同的垃圾回收算法。基于这一点针对世代的垃圾回收算法就很有针对性了。 二十三、多线程 一个线程的生命周期 新建状态:使用new关键字和Thread类或其子类建立一个线程对象,该线程对象就处于新建状态。它保持这个状态直达程序start()这个程序。 就绪状态:当线程对象调用start()方法之后,该线程就进入就绪状态。就绪状态的线程处于就绪队列中,等待JVM里线程调度器的调度。 运行状态:如果就绪状态的线程获取CPU资源,就可以执行run()方法,此时的线程处于运行状态。处于运行时的状态最为复杂,可以变为阻塞状态、就绪状态、死亡状态。 阻塞状态:线程执行了sleep(睡眠)、suspend(挂起)等方法,失去所占用资源之后,该线程从运行状态进入阻塞状态。在睡眠时间已到或获得设备资源后可以重新进入就绪状态。 阻塞状态可以分为三种:①、等待阻塞:运行状态中的线程执行wait()方法;②、同步阻塞:线程在获取synchronized同步锁失败; ③、其他阻塞 死亡状态:一个运行时状态的线程完成任务或者其他终止条件发生时,该线程切换到终止状态。 线程与进程的区别 程序是一段静态的代码,一个进程可以有一个或者多个线程,每个线程都有唯一的标识 区别:①、进程大体分为数据区、代码区、栈区、堆区。多个进程之间的内部数据和状态是完全独立的;线程共享进程的数据区、代码区、堆区、只有栈区是独立的。所以线程切换代价小于进程切换代价。 ②、一个程序至少有一个进程,一个进程至少有一个线程; ③、线程划分尺度小于进程、多线程的程序并发高; ④、进程在执行过程中拥有独立的内存单元,而多线程共享内存,从而极大地提高了程序运行效率; 什么导致线程阻塞 1、调用sleep(毫秒),使得线程进入睡眠状态; 2、调用suspend()暂停线程执行。除非线程收到resume()消息否则返回不可运行状态; 3、调用wait()方法暂停线程执行。除非调用notify()或者notifyAll()消息,否则不可运行; 4、线程正在等候IO操作的完成; 5、线程试图调用另一个对象的同步方法,但是那个对象处于锁定状态暂时无法使用。 多线程的实现方法 1、实现Runnable接口; 2、继承Thread类本身; 3、通过callable和Future创建线程(Java 5 之后出现); 实现Runnable接口相比继承Thread类有如下优势 1、可以避免Java单继承的特性带来的局限性; 2、增强程序的健壮性,代码可以被多个程序共享,代码与数据是独立的; 3、适合多个相同程序代码的线程区处理同一资源的情况 同步有几种实现方法,都是什么? 两种 synchronized wait和notify 锁的等级 方法锁、对象锁、类锁 同步和异步的区别? 同步:A线程请求某资源时,B线程占用该资源,则A只能等待下去 异步:A线程请求某个资源时,B线程占用该资源,则A无需等待可以请求。 sleep和wait的区别 ①、sleep:线程休息;wait:线程挂起。 ②、sleep方法属于Thread类的方法;wait属于Object类方法 ③、sleep:sleep正在执行的线程主动放出cpu,指定时间后cpu回到该线程继续向下执行。注意sleep只是让出CPU而并不是释放同步资源锁; wait:当前线程让自己暂时退让出同步资源锁,以便其他正在等待该资源的线程得到该资源而运行,只有调用notify方法之后调用wait方法的线程才会接触wait状态进而参与竞争同步资源锁,进而执行 Java线程池线程同步 同步操作产生的原因:当多个线程同时访问对象并要求操作相同资源时,分割了原子操作就有可能出现数据的不一致或数据不完整情况,为了避免发生这种情况,我们会采取同步机制。 synchronized修饰符实现的同步机制叫做互斥锁机制。 互斥锁:每个对象都有一个锁标记,当线程拥有锁机制的时候才可访问这个资源,没有锁标记便进入锁池。任何一个对象系统都会创建一个互斥锁,这个锁为了分配给线程,防止打断原子操作,每个对象锁只能分配给一个线程。 当一个线程进入一个对象的一个synchronized方法后,其他线程是否可进入此对象的其他方法? 可以调用此对象的其他非synchronized方法; 可以调用此对象synchronized static方法; 线程加锁的作用:互斥行为和内存可见性 内存可见性定义 某个线程正在使用对象状态而另一个线程在同时修改该状态,当该状态被修改之后可以立刻被其他线程感知该对象的状态改变了 Atomic、volatile、synchronized区别 1、synchronized是解决多线程共享资源的问题同步机制采用了“以时间换取空间”的做法,访问串行化、对象共享化。同步机制是提供一份变量,让所有线程都可以访问。 2、Atomic是通过原子操作指令+Look-Free完成,从而实现非阻塞的并发问题。 3、Volatile是为了多线程资源共享问题解决了部分需求,在非依赖自身的操作的情况下,对变量的改变将对任何线程可见。 4、ThreadLocal是为了解决多线程资源共享问题,用来提供线程内局部变量,省去参数传递这个不必要的麻烦,做到了“以空间换取时间”的方式。 5、如果是一个类的多个对象想公用对象内部的一个变量,而不想使用static,可以使用浅复制的方式。 并发编程实现内存可见性的方式- - - ->加锁和volatile变量 volatile变量 1、volatile变量是一种脆弱的同步机制,由于访问volatile变量时不会执行加锁操作,因此也就不会执行线程阻塞,因此volatile变量是一种比synchronized关键字轻量级的同步机制; 2、从内存可见度角度来看,写入volatile操作相对于退出同步代码块,读取volatile变量相对于进入同步代码块; 3、代码中过度使用volatile编写来控制可见性,通常会比使用锁更加脆弱和难以理解。 4、volatile只能保证可见性,不能保证原子性。 使用volatile的情景: 1、对变量的读写操作不依赖变量的当前值,或者可以保证只有单个线程更新变量的值; 2、该变量没有包含在具有其他变量的不变式中。 守护线程与阻塞线程的四种情况 用户线程:运行在前台的线程; 守护线程:运行在后台的线程,为其他前台线程的运行变量提供便利服务的,仅当非守护线程运行时,才需要守护线程例如垃圾回收线程; 可以人为创建守护线程,通过Thread的setDeamon(ture)方法设置当前线程为守护线程。 禁止在守护线程内创建耗时操作,比如IO操作 setDeamon(ture)方法必须在调用线程的start()方法之前设置,否则会抛出IllegalThreadStateException异常。 守护线程内产生的新线程也是守护线程。 死锁 线程A持有互斥锁lock1,线程B持有互斥锁lock2。当线程A持有lock1时,师徒获取lock2,因为B持有lock2,因此线程A会阻塞等待线程B对lock2的释放。如果此时B在持有lock2的时候也试图获取lock1,因为A持有lock1,因此线程B会阻塞等待A对lock1的释放。二者都在等待对方所持有的锁释放,而二者却又都没释放自己所持有的锁,这时二者会一直阻塞下去,这种情况为死锁现象。 如何避免死锁现象产生 1、只在必要的最短时间内持有锁,可以考虑使用同步语句块代替整个同步方法; 2、尽可能不编写在同一时刻需要持有多个锁的代码,如果不可避免则确保线程持有第二个锁的时间尽量短; 3、创建一个大锁来代替若干个小锁。 可重入内置锁 使用wait/notify/notifyAll实现线程间通信 可以通过调用Object对象的wait()方法和notify()方法或者说notifyAll方法来实现线程间通信。在线程中调用wait()方法,将阻塞等待其他线程的通知,在线程中调用notify()方法或notifyAll方法,将通知其他线程wait()方法处返回。 notify()、notifyAll()、wait()、wait(long)和wait(long,int),他们都被声明为final,因此在子类中不能覆写任何一个方法。 如果调用wait()时,没有持有适当的锁,则抛出IllegalMonitorStateException; 如果调用notify()时没有持有适当的锁,也会抛出IllegalMonitorStateException 如果线程调用了对象的wait方法,那么线程便会处于对该对象的等待池中,等待池中的线程不会去竞争该对象的锁; 当线程调用了对象的notiAll方法或者notify方法,被唤醒的线程便会进入该对象的锁池中,锁池中的线程会去竞争该对象锁; 优先级高的线程竞争到对象锁的概率大,如果没有竞争到对象锁那么他会留在锁池中只有线程再次调用wait方法的时候,它才会再次进入等待池中。竞争到对象锁的线程则会继续向下执行,直到执行完了synchronized代码块,才会释放掉对象锁,此时锁池内线程会继续竞争该对象锁。 Error和Exception的区别 Error是Throwable的子类用于标记严重错误,合理的应用程序不可以用try/catch这种错误。绝大多数错误都是非正常的,不应该出现的。 Exception是Throwable的子类,用于指示合理的程序想去catch的条件,即它仅仅是一种程序运行的条件,而非严重错误。 checked exceptions: 通常是从一个可以恢复的程序中抛出来的,并且最好能够从这种异常中使用程序恢复。比如FileNotFoundException, ParseException等。 unchecked exceptions:就是程序中的bug Java中的异常处理机制的简单原理和应用 Java中通过面向对象的方式,把各种异常进行了分类,并且提供了良好的接口,在Java中每一个异常就是一个的对象。当一个方法抛出异常的时候便抛出了一个异常对象,该对象内包含异常的信息,调用这个对象的方法就可以捕获到这个异常并进行处理。 try/catch的执行过程 一般情况由try来执行一段程序,如果出现异常,系统则会抛出一个异常,此时程序员可以通过他的类型进行捕捉(catch操作),或在最后(finally)由缺省处理器来进行处理。 用try来指定一块预防所有“异常”的程序。紧跟在try程序后面,应包含一个catch子句来指定你想要捕捉的“异常”的类型。throw语句用来明确地抛出一个“异常”。throws用来标明一个成员函可能抛出的各种“异常”。Finally为确保一段代码不管发生什么“异常”都被执行一段代码。 try{ return} catch{} finally{}; return 还是 finally 先执行? 任何执行try或者catch内的return语句之前,都会先执行finally语句,如果finally存在的话。 如果finally中有return语句,那么程序就return了,所以finally中的return是一定会被return的 在try语句中,在执行return语句时,要返回的结果已经准备好了,就在此时,程序转到finally执行了。在转去之前,try中先把要返回的结果存放到不同于x的局部变量中去,执行完finally之后,在从中取出返回结果,因此,即使finally中对变量x进行了改变,但是不会影响返回结果。 二十四、序列化 对象Object读写是哪两个流 ObjectInputStream ObjectOutputStream 什么是Java序列化,如何实现序列化? 序列化就是一种用来处理对象流的机制,所谓对象流就是讲对象的内容流化。可以对流化后的对象进行读写操作,也可将流化后的对象传输于网络之间。序列化是为了解决在对对象流进行读写操作时所引发的问题。 实现:Serializable接口和Parcelable接口 Serializable和Parcelable的区别 两者最大的区别在于存储媒介的不同,Serializable使用IO读写存储在硬盘上,而Parcelable是直接在内存中读写,很明显内存的读写速度通常大于IO读写,所以在Android中通常优先选择Parcelable。 二十五、反射 反射机制 运行状态中,对于任意一个类,都能够知道这类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能被称为Java语言的反射机制。 反射机制的用处 1、观察或者操作应程序的运行时行为; 2、调试或测试程序,因为可以直接访问方法、构造函数和成员字段; 3、通过名字调用不知道的方法并使用该信息来创建对象和调用方法。 二十六、泛型 泛型的优缺点 优点: 使用泛型可以最大限度的重用代码、保护类的安全以及提高性能。 缺点: 性能上不如数组快 二十七、网络 网络参考模型 四层分法:应用层、运输层、网络层、网络接口层 七层分法:应用层、表示层、会话层、运输层、网络层、数据链路层、网络层 Tcp与UDP的区别 1、tcp是面向有链接的通信服务;udp是面向无连接的通信服务 2、tcp传输可靠;udp传输不可靠、会丢包 3、tcp保证数据顺序;udp不保证数据顺序; 4、tcp无边界;udp有边界; 5、tcp传输速度慢;udp传输速度快; 6、tcp面向字节流;udp面向报文 7、tcp一对一;udp一对一或者一对多 TCP:面向连接、传输可靠(保证数据正确性,保证数据顺序)、用于传输大量数据(流模式)、速度慢,建立连接需要开销较多(时间,系统资源)。 UDP:面向非连接、传输不可靠、用于传输少量数据(数据包模式)、速度快。 get和post请求的区别 1、get请求能被缓存;post请求不能被缓存 2、get保存浏览器浏览记录;post不保存浏览器浏览记录; 3、get请求的url可以保存为浏览器书签;post的不可以; 4、get请求长度有限制;post请求长度无限制 5、get请求主要用以获取数据;post提交数据 6、post请求相对安全 Tcp的三次握手 1、客户端发送:SYN=1,SEQ=X,端口号 2、服务的回复:SYN=1,ACK=X+1,SEQ=Y 3、客户端发送:ACK=Y+1,SEQ=X+1 tcp的四次挥手 1、A向B提出停止连接请求,FIN = 1 2、B收到,ACK = 1 3、B向A提出停止连接请求,FIN = 1 4、A收到,ACK = 1 优点:稳定可靠 缺点:传输慢效率低、容易受攻击 udp传输的优缺点 优点:传输速率快,较安全 缺点:不可靠、不稳定 用udp进行通信如何知道目标机是否获得到数据包? 仿TCP的做法,每发一个UDP包,都在里面加一个SEQ序号,接收方收到包后,将SEQ序号回复给发送方。如果发送方在指定时间以内没有收到回应,说明丢包了。 为什么udp比tcp快? 1、无需三次握手 2、tcp有拥塞控制,控制流量等机制 为什么tcp比udp可靠? 1、TCP是面向有连接的,建立连接之后才发送数据;而UDP则不管对方存不存在都会发送数据。 2、TCP有确认机制,接收端每收到一个正确包都会回应给发送端。超时或者数据包不完整的话发送端会重传。UDP没有,因此可能丢包。 什么时候使用Tcp? 当对网络通信质量有要求的时候 例如 浏览器 什么时候使用udp? 当对网络通讯质量要求不高的时候,要求网络通讯速度能尽量的快,这时就可以使用UDP TCP无边界,UDP有边界 TCP:客户端分多次发送数据给服务器,若服务器的缓冲区够大,那么服务器端会在客户端发送完之后一次性接收过来,所以是无边界的; udp:客户端每发送一次,服务器端就会接收一次,也就是说发送多少次就会接收多少次,因此是有边界的。 scoket编程的步骤 1、 创建Socket; 2、 打开连接到Socket的输入/出流; 3、 按照一定的协议对Socket进行读/写操作; 4、关闭Socket.(在实际应用中,并未使用到显示的close,虽然很多文章都推荐如此,不过在我的程序中,可能因为程序本身比较简单,要求不高,所以并未造成什么影响。)

优秀的个人博客,低调大师

PHP面试题集

汗~~做了一下网络上的php题目,不知不觉做到现在.....把答案贴出来 如果有问题请欢迎补充和指正 1、用PHP打印出前一天的时间格式是2006-5-10 22:21:21(2分) $a = date("Y-m-d H:i:s", strtotime("-1 day")); print_r($a); 2、echo(),print(),print_r()的区别(3分) echo 和print不是一个函数,是一个语言结构 int print(string $arg), 只有一个参数 echo arg1,arg1,arg2; 可以输出多个参数,返回void echo和print只能打印出string,不能打印出结构 print_r能打印出结构 比如 $arr = array("key"=>"value"); print_r($arr); 3、能够使HTML和PHP分离开使用的模板(1分) smarty,phplib 4、使用哪些工具进行版本控制?(1分) svn,git,cvs 5、如何实现字符串翻转?(3分) 英文: strrev($a) 中文或其他文字: 中文:GB2312, 代码是使用GB2312编码 <?php function reverse($str) { $ret = ""; len=mbstrwidth(len=mbstrwidth(str,"GB2312"); for( i=0;i=0;i< len;len;i++) { arr[]=mbsubstr(arr[]=mbsubstr(str, $i, 1, "GB2312"); } return implode("", array_reverse($arr)); } print_r(reverse("你好")); --------------------------------------------------------------- 6、优化MYSQL数据库的方法。(4分,多写多得) 语句方面: 1 使用索引,增加查询效率 2 优化查询语句,提高索引命中率 数据库涉及方面: 1 构造分库分表,提高数据库的存储和扩展能力 2 根据需要使用不同的存储引擎 7、PHP的意思(送1分) 超级文本预处理语言 Hypertext PreProcessor 8、MYSQL取得当前时间的函数是?,格式化日期的函数是(2分) CURRENT_TIMESTAMP() DATE_FORMAT() select DATE_FORMAT("2011-11-21 10:10:10", "%Y-%m-%d"); 9、实现中文字串截取无乱码的方法。(3分) mb_substr($str, 1, 1, "GB2312"); --------------------------------------------------------------- 10、您是否用过版本控制软件? 如果有您用的版本控制软件的名字是?(1分) svn git 11、您是否用过模板引擎? 如果有您用的模板引擎的名字是?(1分) smarty 12、请简单阐述您最得意的开发之作(4分) XXX 13、对于大流量的网站,您采用什么样的方法来解决访问量问题?(4分) 1 有效使用缓存,增加缓存命中率 2 使用负载均衡 3 对静态文件使用CDN进行存储和加速 4 想法减少数据库的使用 5 查看出现统计的瓶颈在哪里 ----------------------------------------------------------------- 14、用PHP写出显示客户端IP与服务器IP的代码1分) $_SERVER["REMOTE_ADDR"] $_SERVER["SERVER_ADDR"] 15、语句include和require的区别是什么?为避免多次包含同一文件,可用(?)语句代替它们? (2分) 在失败的时候: include产生一个warning,而require产生直接产生错误中断 require在运行前载入 include在运行时载入 require_once include_once 16、如何修改SESSION的生存时间(1分). session_set_cookie_params 17、有一个网页地址, 比如PHP研究室主页: http://www.phpv.net/index.html,如何得到它的内容?($1分) file_get_contents curl 18、在HTTP 1.0中,状态码401的含义是(?);如果返回“找不到文件”的提示,则可用 header 函数,其语句为(?);(2分) 未授权 header("HTTP/1.0 404 Not Found"); fast CGI中: header("Status: 404 Not Found"); 19、在PHP中,heredoc是一种特殊的字符串,它的结束标志必须?(1分) 成对出现 $a = <<EOD good test EOD; 20、谈谈asp,php,jsp的优缺点(1分) asp是需要依赖IIS,是微软开发的语言 php和jsp可以依赖apache或者 nginx等其他服务器 21、谈谈对mvc的认识(1分) model : 数据结构层 view :展现 control : 接收和判断处理输入 ------------------------------------------------------------------- 22、写出发贴数最多的十个人名字的SQL,利用下表:members(id,username,posts,pass,email)(2分) select top 10 id,username from members order by posts desc 23. 请说明php中传值与传引用的区别。什么时候传值什么时候传引用?(2分) &表示传引用 函数中参数传引用会将参数进行改变 一般在输出参数有多个的时候可以考虑使用引用 24. 在PHP中error_reporting这个函数有什么作用? (1分) 设定error的展示级别 25. 请写一个函数验证电子邮件的格式是否正确 (2分) $str = "jianfeng@126.com"; regex="([a−z0−9\.−]+)@([\da−z\.−]+)\.([a−z\.]2,6)regex="([a−z0−9\.−]+)@([\da−z\.−]+)\.([a−z\.]2,6)" ; //正则 return preg_match( regex,regex,str) 26. 简述如何得到当前执行脚本路径,包括所得到参数。(2分) $argc --获取参数数量 $argv --获取参数列表 27.如何修改SESSION的生存时间. (1分) session_set_cookie_params -------------------------------------------------------------------- 28、JS表单弹出对话框函数是?获得输入焦点函数是? (2分) alert() confirm() promopt() focus() 29、JS的转向函数是?怎么引入一个外部JS文件?(2分) window.location.href="#" <script src="#"> </script> 30、foo()和@foo()之间有什么区别?(1分) @代表所有warning忽略 31、如何声明一个名为”myclass”的没有方法和属性的类? (1分) class myclass { } 32、如何实例化一个名为”myclass”的对象?(1分) $myclass = new myclass(); 33、你如何访问和设置一个类的属性? (2分) <?php class A { public $name = "A"; } $a = new A(); n=n=a->name; print_r($n); 34、mysql_fetch_row() 和mysql_fetch_array之间有什么区别? (1分) mysql_fetch_array() 是 mysql_fetch_row() 的扩展版本。除了将数据以数字索引方式储存在数组中之外,还可以将数据作为关联索引储存,用字段名作为键名。 <?php mysql_connect("localhost", "mysql_user", "mysql_password") or die("Could not connect: " . mysql_error()); mysql_select_db("mydb"); $result = mysql_query("SELECT id, name FROM mytable"); while ( row=mysqlfetcharray(row=mysqlfetcharray(result, MYSQL_ASSOC)) { printf ("ID: %s Name: %s", row["id"],row["id"],row["name"]); } mysql_free_result($result); -------------------------------------------------------------------- 35、GD库是做什么用的? (1分) 动态的开放的图片处理库 36、指出一些在PHP输入一段HTML代码的办法。(1分) echo "{html}" echo <<EOD {html} EOD; 37、下面哪个函数可以打开一个文件,以对文件进行读和写操作?(1分) c (a) fget() (b) file_open() (c) fopen() (d) open_file() 38、下面哪个选项没有将 john 添加到users 数组中? (1分) b (a) $users[] = ‘john’; (b) array_add($users,’john’); (c) array_push($users,‘john’); (d) $users ||= ‘john’; 39、下面的程序会输入是否?(1分) 10 $num = 10; function multiply(){ num=num=num * 10; } multiply(); echo $num; ?> 40、使用php写一段简单查询,查出所有姓名为“张三”的内容并打印出来 (2分) 表名 UserName Tel Content Date 张三 13333663366 大专毕业 2006-10-11 张三 13612312331 本科毕业 2006-10-15 张四 021-55665566 中专毕业 2006-10-15 请根据上面的题目完成代码: $mysql_db=mysql_connect("local","root","pass"); @mysql_select_db("DB",$mysql_db); $sql = sprintf("select * from %s where UserName = '%s'", "表名", "张三"); values=mysqlquery(values=mysqlquery(sql); while( item=mysqlfetchqueryarray(item=mysqlfetchqueryarray(values)) { echo sprintf("用户名:%s, 电话 %s, 学历: %s, 毕业日期: %s", item[′UserName′],item[′UserName′],item['Tel'], item[′Content′],item[′Content′],item['Date'] ); } 41、如何使用下面的类,并解释下面什么意思?(3) class test{ function Get_test($num){ num=md5(md5(num=md5(md5(num)."En"); return $num; } } $test = new test(); ret=ret=test->Get_test(11); print_r($ret);exit; 将num进行MD5编码之后生成的32位字符串a1和"En"联系起来之后再进行一次MD5编码 ---------------------------------------------------------------------------- 42、写出 SQL语句的格式 : 插入 ,更新 ,删除 (4分) 表名 UserName Tel Content Date 张三 13333663366 大专毕业 2006-10-11 张三 13612312331 本科毕业 2006-10-15 张四 021-55665566 中专毕业 2006-10-15 (a) 有一新记录(小王 13254748547 高中毕业 2007-05-06)请用SQL语句新增至表中 insert into 表名 values('小王', '13254748547', '高中毕业', '2007-05-06') (b) 请用sql语句把张三的时间更新成为当前系统时间 update 表名 set Date = GETDATE() where UserName = "张三" (c) 请写出删除名为张四的全部记录 delete from 表明 where UserName = "张四" 43、请写出数据类型(int char varchar datetime text)的意思; 请问varchar和char有什么区别(2分) int 整型 char 存储定长 varchar 存储变长 datetime 时间 text 存储变长的 varchar是变长 char(20) 定长 44、MySQ自增类型(通常为表ID字段)必需将其设为(?)字段(1分) auto_increment 45、写出以下程序的输出结果 (1分) $b=201; $c=40; a=a=b>$c?4:5; echo $a; ?> 4 46、检测一个变量是否有设置的函数是否?是否为空的函数是?(2分) isset() empty() ----------------------------------------------------------------------------- 47、取得查询结果集总数的函数是?(1分) mysql_num_rows() 48、$arr = array('james', 'tom', 'symfony'); 请打印出第一个元素的值 (1分) print_r($arr[0]); reset($arr); print_r(current($arr)); print_r(array_shift($arr)); 49、请将41题的数组的值用','号分隔并合并成字串输出(1分) implode 50、 a=′abcdef′;请取出a=′abcdef′;请取出a的值并打印出第一个字母(1分) $a[0]; substr($a, 0, 1); 51、PHP可以和sql server/oracle等数据库连接吗?(1分) 可以 有现成的库 52、请写出PHP5权限控制修饰符(3分) public private protected 53、请写出php5的构造函数和析构函数(2分) public function __construct() { } public function __destruct() { } 编程题 1. 写一个函数,尽可能高效的,从一个标准 url 里取出文件的扩展名 例如: http://www.sina.com.cn/abc/de/fg.php?id=1 需要取出 php 或 .php <?php $url = "http://www.sina.com.cn/abc/de/fg.php?id=1"; arr=parseurl(arr=parseurl(url); pathArr=pathinfo(pathArr=pathinfo(arr['path']); print_r($pathArr['extension']); 3. 写一个函数,算出两个文件的相对路径 如 $a = '/a/b/c/d/e.php'; $b = '/a/b/12/34/c.php'; 计算出 b相对于b相对于a 的相对路径应该是 http://www.cnblogs.com/12/34/c.php将添上 <?php $a = '/a/b/c/d/e.php'; $b = '/a/b/12/34/c.php'; //获取path相对于conpath的相对路径 function sGetRelativePath( path,path,conpath) { pathArr=explode("/",pathArr=explode("/",path); conpathArr=explode("/",conpathArr=explode("/",conpath); $dismatchlen = 0; for( i=0;i=0;i < count( pathArr);pathArr);i++) { if( conpathArr[conpathArr[i] != pathArr[pathArr[i]) { dismatchlen=count(dismatchlen=count(pathArr) - $i; arrLeft=arrayslice(arrLeft=arrayslice(pathArr, $i); break; } } ret=strrepeat("../",ret=strrepeat("../",dismatchlen).implode("/", $arrLeft); return $ret; } print_r(sGetRelativePath( b,b,a)); 3.写一个函数,能够遍历一个文件夹下的所有文件和子文件夹。 <?php function aGetAllFile($folder) { $aFileArr = array(); if(is_dir($folder)) { handle=opendir(handle=opendir(folder); while(( file=readdir(file=readdir(handle)) !== false) { //如果是.或者..则跳过 if( file=="."||file=="."||file == "..") { continue; } if(is_file( folder."/".folder."/".file)) { aFileArr[]=aFileArr[]=file; } else if(is_dir( folder."/".folder."/".file)) { aFileArr[aFileArr[file] = aGetAllFile( folder."/".folder."/".file); } } closedir($handle); } return $aFileArr; } $path = "/home/test/sql"; print_r(aGetAllFile($path)); 本文转自轩脉刃博客园博客,原文链接:http://www.cnblogs.com/yjf512/archive/2012/02/03/2336423.html,如需转载请自行联系原作者

优秀的个人博客,低调大师

linux运维面试精选

1、什么是运维?什么是游戏运维? 1)运维是指大型组织已经建立好的网络软硬件的维护,就是要保证业务的上线与运作的正常, 在他运转的过程中,对他进行维护,他集合了网络、系统、数据库、开发、安全、监控于一身的技术 运维又包括很多种,有DBA运维、网站运维、虚拟化运维、监控运维、游戏运维等等 2)游戏运维又有分工,分为开发运维、应用运维(业务运维)和系统运维 开发运维:是给应用运维开发运维工具和运维平台的 应用运维:是给业务上线、维护和做故障排除的,用开发运维开发出来的工具给业务上线、维护、做故障排查 系统运维:是给应用运维提供业务上的基础设施,比如:系统、网络、监控、硬件等等 总结:开发运维和系统运维给应用运维提供了“工具”和“基础设施”上的支撑 开发运维、应用运维和系统运维他们的工作是环环相扣的 2、在工作中,运维人员经常需要跟运营人员打交道,请问运营人员是做什么工作的? 游戏运营要做的一个事情除了协调工作以外 还需要与各平台沟通,做好开服的时间、开服数、用户导量、活动等计划 3、现在给你三百台服务器,你怎么对他们进行管理? 管理3百台服务器的方式: 1)设定跳板机,使用统一账号登录,便于安全与登录的考量。 2)使用salt、ansiable、puppet进行系统的统一调度与配置的统一管理。 3)建立简单的服务器的系统、配置、应用的cmdb信息管理。便于查阅每台服务器上的各种信息记录。 4、简述raid0 raid1 raid5 三种工作模式的工作原理及特点 RAID,可以把硬盘整合成一个大磁盘,还可以在大磁盘上再分区,放数据 还有一个大功能,多块盘放在一起可以有冗余(备份) RAID整合方式有很多,常用的:0 1 5 10 RAID 0,可以是一块盘和N个盘组合 其优点读写快,是RAID中最好的 缺点:没有冗余,一块坏了数据就全没有了 RAID 1,只能2块盘,盘的大小可以不一样,以小的为准 10G+10G只有10G,另一个做备份。它有100%的冗余,缺点:浪费资源,成本高 RAID 5 ,3块盘,容量计算10*(n-1),损失一块盘 特点,读写性能一般,读还好一点,写不好 冗余从好到坏:RAID1 RAID10 RAID 5 RAID0 性能从好到坏:RAID0 RAID10 RAID5 RAID1 成本从低到高:RAID0 RAID5 RAID1 RAID10 单台服务器:很重要盘不多,系统盘,RAID1 数据库服务器:主库:RAID10 从库 RAID5\RAID0(为了维护成本,RAID10) WEB服务器,如果没有太多的数据的话,RAID5,RAID0(单盘) 有多台,监控、应用服务器,RAID0 RAID5 我们会根据数据的存储和访问的需求,去匹配对应的RAID级别 5、LVS、Nginx、HAproxy有什么区别?工作中你怎么选择? LVS: 是基于四层的转发 HAproxy: 是基于四层和七层的转发,是专业的代理服务器 Nginx: 是WEB服务器,缓存服务器,又是反向代理服务器,可以做七层的转发 区别: LVS由于是基于四层的转发所以只能做端口的转发 而基于URL的、基于目录的这种转发LVS就做不了 工作选择: HAproxy和Nginx由于可以做七层的转发,所以URL和目录的转发都可以做 在很大并发量的时候我们就要选择LVS,像中小型公司的话并发量没那么大 选择HAproxy或者Nginx足已,由于HAproxy由是专业的代理服务器 配置简单,所以中小型企业推荐使用HAproxy 6、Squid、Varinsh和Nginx有什么区别,工作中你怎么选择? Squid、Varinsh和Nginx都是代理服务器 什么是代理服务器: 能当替用户去访问公网,并且能把访问到的数据缓存到服务器本地,等用户下次再访问相同的资 源的时候,代理服务器直接从本地回应给用户,当本地没有的时候,我代替你去访问公网,我接 收你的请求,我先在我自已的本地缓存找,如果我本地缓存有,我直接从我本地的缓存里回复你 如果我在我本地没有找到你要访问的缓存的数据,那么代理服务器就会代替你去访问公网 区别: 1)Nginx本来是反向代理/web服务器,用了插件可以做做这个副业 但是本身不支持特性挺多,只能缓存静态文件 2)从这些功能上。varnish和squid是专业的cache服务,而nginx这些是第三方模块完成 3)varnish本身的技术上优势要高于squid,它采用了可视化页面缓存技术 在内存的利用上,Varnish比Squid具有优势,性能要比Squid高。 还有强大的通过Varnish管理端口,可以使用正则表达式快速、批量地清除部分缓存 它是内存缓存,速度一流,但是内存缓存也限制了其容量,缓存页面和图片一般是挺好的 4)squid的优势在于完整的庞大的cache技术资料,和很多的应用生产环境 工作中选择: 要做cache服务的话,我们肯定是要选择专业的cache服务,优先选择squid或者varnish。 7、Tomcat和Resin有什么区别,工作中你怎么选择? 区别:Tomcat用户数多,可参考文档多,Resin用户数少,可考虑文档少 最主要区别则是Tomcat是标准的java容器,不过性能方面比resin的要差一些 但稳定性和java程序的兼容性,应该是比resin的要好 工作中选择:现在大公司都是用resin,追求性能;而中小型公司都是用Tomcat,追求稳定和程序的兼容 8、什么是中间件?什么是jdk? 中间件介绍: 中间件是一种独立的系统软件或服务程序,分布式应用软件借助这种软件在不同的技术之间共享资源 中间件位于客户机/ 服务器的操作系统之上,管理计算机资源和网络通讯 是连接两个独立应用程序或独立系统的软件。相连接的系统,即使它们具有不同的接口 但通过中间件相互之间仍能交换信息。执行中间件的一个关键途径是信息传递 通过中间件,应用程序可以工作于多平台或OS环境。 jdk:jdk是Java的开发工具包 它是一种用于构建在 Java 平台上发布的应用程序、applet 和组件的开发环境 9、讲述一下Tomcat8005、8009、8080三个端口的含义? 8005==》 关闭时使用 8009==》 为AJP端口,即容器使用,如Apache能通过AJP协议访问Tomcat的8009端口 8080==》 一般应用使用 10、什么叫CDN? 即内容分发网络 其目的是通过在现有的Internet中增加一层新的网络架构,将网站的内容发布到 最接近用户的网络边缘,使用户可就近取得所需的内容,提高用户访问网站的速度 11、什么叫网站灰度发布? 灰度发布是指在黑与白之间,能够平滑过渡的一种发布方式 AB test就是一种灰度发布方式,让一部用户继续用A,一部分用户开始用B 如果用户对B没有什么反对意见,那么逐步扩大范围,把所有用户都迁移到B上面 来 灰度发布可以保证整体系统的稳定,在初始灰度的时候就可以发现、调整问题,以保证其影响度 12、简述DNS进行域名解析的过程? 用户要访问www.baidu.com,会先找本机的host文件,再找本地设置的DNS服务器,如果也没有的话,就去网络中找根服务器,根服务器反馈结果,说只能提供一级域名服务器.cn,就去找一级域名服务器,一级域名服务器说只能提供二级域名服务器.com.cn,就去找二级域名服务器,二级域服务器只能提供三级域名服务器.baidu.com.cn,就去找三级域名服务器,三级域名服务器正好有这个网站www.baidu.com,然后发给请求的服务器,保存一份之后,再发给客户端 13、RabbitMQ是什么东西? RabbitMQ也就是消息队列中间件,消息中间件是在消息的传息过程中保存消息的容器 消息中间件再将消息从它的源中到它的目标中标时充当中间人的作用 队列的主要目的是提供路由并保证消息的传递;如果发送消息时接收者不可用 消息队列不会保留消息,直到可以成功地传递为止,当然,消息队列保存消息也是有期限地 14、讲一下Keepalived的工作原理? 在一个虚拟路由器中,只有作为MASTER的VRRP路由器会一直发送VRRP通告信息, BACKUP不会抢占MASTER,除非它的优先级更高。当MASTER不可用时(BACKUP收不到通告信息) 多台BACKUP中优先级最高的这台会被抢占为MASTER。这种抢占是非常快速的(<1s),以保证服务的连续性 由于安全性考虑,VRRP包使用了加密协议进行加密。BACKUP不会发送通告信息,只会接收通告信息 15、讲述一下LVS三种模式的工作过程? LVS 有三种负载均衡的模式,分别是VS/NAT(nat 模式) VS/DR(路由模式) VS/TUN(隧道模式) 一、NAT模式(VS-NAT) 原理:就是把客户端发来的数据包的IP头的目的地址,在负载均衡器上换成其中一台RS的IP地址 并发至此RS来处理,RS处理完后把数据交给负载均衡器,负载均衡器再把数据包原IP地址改为自己的IP 将目的地址改为客户端IP地址即可期间,无论是进来的流量,还是出去的流量,都必须经过负载均衡器 优点:集群中的物理服务器可以使用任何支持TCP/IP操作系统,只有负载均衡器需要一个合法的IP地址 缺点:扩展性有限。当服务器节点(普通PC服务器)增长过多时,负载均衡器将成为整个系统的瓶颈 因为所有的请求包和应答包的流向都经过负载均衡器。当服务器节点过多时 大量的数据包都交汇在负载均衡器那,速度就会变慢! 二、IP隧道模式(VS-TUN) 原理:首先要知道,互联网上的大多Internet服务的请求包很短小,而应答包通常很大 那么隧道模式就是,把客户端发来的数据包,封装一个新的IP头标记(仅目的IP)发给RS RS收到后,先把数据包的头解开,还原数据包,处理后,直接返回给客户端,不需要再经过 负载均衡器。注意,由于RS需要对负载均衡器发过来的数据包进行还原,所以说必须支持 IPTUNNEL协议,所以,在RS的内核中,必须编译支持IPTUNNEL这个选项 优点:负载均衡器只负责将请求包分发给后端节点服务器,而RS将应答包直接发给用户 所以,减少了负载均衡器的大量数据流动,负载均衡器不再是系统的瓶颈,就能处理很巨大的请求量 这种方式,一台负载均衡器能够为很多RS进行分发。而且跑在公网上就能进行不同地域的分发。 缺点:隧道模式的RS节点需要合法IP,这种方式需要所有的服务器支持”IP Tunneling” (IP Encapsulation)协议,服务器可能只局限在部分Linux系统上 三、直接路由模式(VS-DR) 原理:负载均衡器和RS都使用同一个IP对外服务但只有DR对ARP请求进行响应 所有RS对本身这个IP的ARP请求保持静默也就是说,网关会把对这个服务IP的请求全部定向给DR 而DR收到数据包后根据调度算法,找出对应的RS,把目的MAC地址改为RS的MAC(因为IP一致) 并将请求分发给这台RS这时RS收到这个数据包,处理完成之后,由于IP一致,可以直接将数据返给客户 则等于直接从客户端收到这个数据包无异,处理后直接返回给客户端 由于负载均衡器要对二层包头进行改换,所以负载均衡器和RS之间必须在一个广播域 也可以简单的理解为在同一台交换机上 优点:和TUN(隧道模式)一样,负载均衡器也只是分发请求,应答包通过单独的路由方法返回给客户端 与VS-TUN相比,VS-DR这种实现方式不需要隧道结构,因此可以使用大多数操作系统做为物理服务器。 缺点:(不能说缺点,只能说是不足)要求负载均衡器的网卡必须与物理网卡在一个物理段上。 16、mysql的innodb如何定位锁问题,mysql如何减少主从复制延迟? mysql的innodb如何定位锁问题: 在使用 show engine innodb status检查引擎状态时,发现了死锁问题 在5.5中,information_schema 库中增加了三个关于锁的表(MEMORY引擎) innodb_trx ## 当前运行的所有事务 innodb_locks ## 当前出现的锁 innodb_lock_waits ## 锁等待的对应关系 mysql如何减少主从复制延迟: 如果延迟比较大,就先确认以下几个因素: 从库硬件比主库差,导致复制延迟 主从复制单线程,如果主库写并发太大,来不及传送到从库 就会导致延迟。更高版本的mysql可以支持多线程复制 慢SQL语句过多 网络延迟 master负载 主库读写压力大,导致复制延迟,架构的前端要加buffer及缓存层 slave负载 一般的做法是,使用多台slave来分摊读请求,再从这些slave中取一台专用的服务器 只作为备份用,不进行其他任何操作.另外, 2个可以减少延迟的参数: –slave-net-timeout=seconds 单位为秒 默认设置为 3600秒 #参数含义:当slave从主数据库读取log数据失败后,等待多久重新建立连接并获取数据 –master-connect-retry=seconds 单位为秒 默认设置为 60秒 #参数含义:当重新建立主从连接时,如果连接建立失败,间隔多久后重试 通常配置以上2个参数可以减少网络问题导致的主从数据同步延迟 MySQL数据库主从同步延迟解决方案 最简单的减少slave同步延时的方案就是在架构上做优化,尽量让主库的DDL快速执行 还有就是主库是写,对数据安全性较高,比如sync_binlog=1,innodb_flush_log_at_trx_commit = 1 之类的设置,而slave则不需要这么高的数据安全,完全可以讲sync_binlog设置为0或者关闭binlog innodb_flushlog也可以设置为0来提高sql的执行效率。另外就是使用比主库更好的硬件设备作为slave 17、如何重置mysql root密码? 一、 在已知MYSQL数据库的ROOT用户密码的情况下,修改密码的方法: 1、 在SHELL环境下,使用mysqladmin命令设置: mysqladmin –u root –p password “新密码” 回车后要求输入旧密码 2、 在mysql>环境中,使用update命令,直接更新mysql库user表的数据: Update mysql.user set password=password(‘新密码’) where user=’root’; flush privileges; 注意:mysql语句要以分号”;”结束 3、 在mysql>环境中,使用grant命令,修改root用户的授权权限。 grant all on *.* to root@’localhost’ identified by ‘新密码’; 二、 如查忘记了mysql数据库的ROOT用户的密码,又如何做呢?方法如下: 1、 关闭当前运行的mysqld服务程序:service mysqld stop(要先将mysqld添加为系统服务) 2、 使用mysqld_safe脚本以安全模式(不加载授权表)启动mysqld 服务 /usr/local/mysql/bin/mysqld_safe --skip-grant-table & 3、 使用空密码的root用户登录数据库,重新设置ROOT用户的密码 #mysql -u root Mysql> Update mysql.user set password=password(‘新密码’) where user=’root’; Mysql> flush privileges; 18、lvs/nginx/haproxy优缺点 Nginx的优点是: 1、工作在网络的7层之上,可以针对http应用做一些分流的策略,比如针对域名、目录结构 它的正则规则比HAProxy更为强大和灵活,这也是它目前广泛流行的主要原因之一 Nginx单凭这点可利用的场合就远多于LVS了。 2、Nginx对网络稳定性的依赖非常小,理论上能ping通就就能进行负载功能,这个也是它的优势之一 相反LVS对网络稳定性依赖比较大,这点本人深有体会; 3、Nginx安装和配置比较简单,测试起来比较方便,它基本能把错误用日志打印出来 LVS的配置、测试就要花比较长的时间了,LVS对网络依赖比较大。 4、可以承担高负载压力且稳定,在硬件不差的情况下一般能支撑几万次的并发量,负载度比LVS相对小些。 5、Nginx可以通过端口检测到服务器内部的故障,比如根据服务器处理网页返回的状态码、超时等等,并且会把返回错误的请求重新提交到另一个节点,不过其中缺点就是不支持url来检测。比如用户正在上传一个文件,而处理该上传的节点刚好在上传过程中出现故障,Nginx会把上传切到另一台服务器重新处理,而LVS就直接断掉了 如果是上传一个很大的文件或者很重要的文件的话,用户可能会因此而不满。 6、Nginx不仅仅是一款优秀的负载均衡器/反向代理软件,它同时也是功能强大的Web应用服务器 LNMP也是近几年非常流行的web架构,在高流量的环境中稳定性也很好。 7、Nginx现在作为Web反向加速缓存越来越成熟了,速度比传统的Squid服务器更快,可考虑用其作为反向代理加速器 8、Nginx可作为中层反向代理使用,这一层面Nginx基本上无对手,唯一可以对比Nginx的就只有lighttpd了 不过lighttpd目前还没有做到Nginx完全的功能,配置也不那么清晰易读,社区资料也远远没Nginx活跃 9、Nginx也可作为静态网页和图片服务器,这方面的性能也无对手。还有Nginx社区非常活跃,第三方模块也很多 Nginx的缺点是: 1、Nginx仅能支持http、https和Email协议,这样就在适用范围上面小些,这个是它的缺点 2、对后端服务器的健康检查,只支持通过端口来检测,不支持通过url来检测 不支持Session的直接保持,但能通过ip_hash来解决 LVS:使用Linux内核集群实现一个高性能、高可用的负载均衡服务器 它具有很好的可伸缩性(Scalability)、可靠性(Reliability)和可管理性(Manageability) LVS的优点是: 1、抗负载能力强、是工作在网络4层之上仅作分发之用,没有流量的产生 这个特点也决定了它在负载均衡软件里的性能最强的,对内存和cpu资源消耗比较低 2、配置性比较低,这是一个缺点也是一个优点,因为没有可太多配置的东西 所以并不需要太多接触,大大减少了人为出错的几率 3、工作稳定,因为其本身抗负载能力很强,自身有完整的双机热备方案 如LVS+Keepalived,不过我们在项目实施中用得最多的还是LVS/DR+Keepalived 4、无流量,LVS只分发请求,而流量并不从它本身出去,这点保证了均衡器IO的性能不会收到大流量的影响。 5、应用范围较广,因为LVS工作在4层,所以它几乎可对所有应用做负载均衡,包括http、数据库、在线聊天室等 LVS的缺点是: 1、软件本身不支持正则表达式处理,不能做动静分离 而现在许多网站在这方面都有较强的需求,这个是Nginx/HAProxy+Keepalived的优势所在 2、如果是网站应用比较庞大的话,LVS/DR+Keepalived实施起来就比较复杂了 特别后面有Windows Server的机器的话,如果实施及配置还有维护过程就比较复杂了 相对而言,Nginx/HAProxy+Keepalived就简单多了。 HAProxy的特点是: 1、HAProxy也是支持虚拟主机的。 2、HAProxy的优点能够补充Nginx的一些缺点,比如支持Session的保持,Cookie的引导 同时支持通过获取指定的url来检测后端服务器的状态 3、HAProxy跟LVS类似,本身就只是一款负载均衡软件 单纯从效率上来讲HAProxy会比Nginx有更出色的负载均衡速度,在并发处理上也是优于Nginx的 4、HAProxy支持TCP协议的负载均衡转发,可以对MySQL读进行负载均衡 对后端的MySQL节点进行检测和负载均衡,大家可以用LVS+Keepalived对MySQL主从做负载均衡 5、HAProxy负载均衡策略非常多,HAProxy的负载均衡算法现在具体有如下8种: ①roundrobin,表示简单的轮询,这个不多说,这个是负载均衡基本都具备的; ② static-rr,表示根据权重,建议关注; ③leastconn,表示最少连接者先处理,建议关注; ④ source,表示根据请求源IP,这个跟Nginx的IP_hash机制类似 我们用其作为解决session问题的一种方法,建议关注; ⑤ri,表示根据请求的URI; ⑥rl_param,表示根据请求的URl参数’balance url_param’ requires an URL parameter name; ⑦hdr(name),表示根据HTTP请求头来锁定每一次HTTP请求; ⑧rdp-cookie(name),表示根据据cookie(name)来锁定并哈希每一次TCP请求。 19、mysql数据备份工具 mysqldump工具 mysqldump是mysql自带的备份工具,目录在bin目录下面:/usr/local/mysql/bin/mysqldump 支持基于innodb的热备份,但是由于是逻辑备份,所以速度不是很快,适合备份数据比较小的场景 Mysqldump完全备份+二进制日志可以实现基于时间点的恢复。 基于LVM快照备份 在物理备份中,有基于文件系统的物理备份(LVM的快照),也可以直接用tar之类的命令对整个数据库目录 进行打包备份,但是这些只能进行泠备份,不同的存储引擎备份的也不一样,myisam自动备份到表级别 而innodb不开启独立表空间的话只能备份整个数据库。 tar包备份 percona提供的xtrabackup工具 支持innodb的物理热备份,支持完全备份,增量备份,而且速度非常快,支持innodb存储引起的数据在不同 数据库之间迁移,支持复制模式下的从机备份恢复备份恢复,为了让xtrabackup支持更多的功能扩展 可以设立独立表空间,打开 innodb_file_per_table功能,启用之后可以支持单独的表备份 20、keepalive的工作原理和如何做到健康检查 keepalived是以VRRP协议为实现基础的,VRRP全称Virtual Router Redundancy Protocol,即虚拟路由冗余协议。 虚拟路由冗余协议,可以认为是实现路由器高可用的协议,即将N台提供相同功能的路由器组成一个路由器组 这个组里面有一个master和多个backup,master上面有一个对外提供服务的vip(该路由器所在局域网内 其他机器的默认路由为该vip),master会发组播,当backup收不到vrrp包时就认为master宕掉了 这时就需要根据VRRP的优先级来选举一个backup当master。这样就可以保证路由器的高可用了 keepalived主要有三个模块,分别是core、check和vrrp。core模块为keepalived的核心,负责主进程的启动、维护 及全局配置文件的加载和解析。check负责健康检查,包括常见的各种检查方式,vrrp模块是来实现VRRP协议的 Keepalived健康检查方式配置 HTTP_GET|SSL_GET HTTP_GET | SSL_GET { url { path /# HTTP/SSL 检查的url可以是多个 digest <STRING> # HTTP/SSL 检查后的摘要信息用工具genhash生成 status_code 200# HTTP/SSL 检查返回的状态码 } connect_port 80 # 连接端口 bindto<IPADD> connect_timeout 3 # 连接超时时间 nb_get_retry 3 # 重连次数 delay_before_retry 2 #连接间隔时间 } 21、统计ip访问情况,要求分析nginx访问日志,找出访问页面数量在前十位的ip cat access.log | awk '{print $1}' | uniq -c | sort -rn | head -10 22、使用tcpdump监听主机为192.168.1.1,tcp端口为80的数据,同时将输出结果保存输出到tcpdump.log tcpdump 'host 192.168.1.1 and port 80' > tcpdump.log 23、如何将本地80 端口的请求转发到8080 端口,当前主机IP 为192.168.2.1 iptables -A PREROUTING -d 192.168.2.1 -p tcp -m tcp -dport 80 -j DNAT-to-destination 192.168.2.1:8080 24、简述raid0 raid1 raid5 三种工作模式的工作原理及特点 RAID 0:带区卷,连续以位或字节为单位分割数据,并行读/写于多个磁盘上,因此具有很高的数据传输率 但它没有数据冗余,RAID 0 只是单纯地提高性能,并没有为数据的可靠性提供保证 而且其中的一个磁盘失效将影响到所有数据。因此,RAID 0 不能应用于数据安全性要求高的场合 RAID 1:镜像卷,它是通过磁盘数据镜像实现数据冗余,在成对的独立磁盘上产生互为备份的数据 不能提升写数据效率。当原始数据繁忙时,可直接从镜像拷贝中读取数据,因此RAID1 可以提高读取性能 RAID 1 是磁盘阵列中单位成本最高的,镜像卷可用容量为总容量的1/2,但提供了很高的数据安全性和可用性 当一个磁盘失效时,系统可以自动切换到镜像磁盘上读写,而不需要重组失效的数据 RAID5:至少由3块硬盘组成,分布式奇偶校验的独立磁盘结构,它的奇偶校验码存在于所有磁盘上 任何一个硬盘损坏,都可以根据其它硬盘上的校验位来重建损坏的数据(最多允许1块硬盘损坏) 所以raid5可以实现数据冗余,确保数据的安全性,同时raid5也可以提升数据的读写性能 25、你对现在运维工程师的理解和以及对其工作的认识 运维工程师在公司当中责任重大,需要保证时刻为公司及客户提供最高、最快、最稳定、最安全的服务 运维工程师的一个小小的失误,很有可能会对公司及客户造成重大损失 因此运维工程师的工作需要严谨及富有创新精神 26、实时抓取并显示当前系统中tcp 80端口的网络数据信息,请写出完整操作命令 tcpdump -nn tcp port 80 27、服务器开不了机怎么解决一步步的排查 A、造成服务器故障的原因可能有以下几点: 3.PNG B、如何排查服务器故障的处理步骤如下: 3.PNG 28、Linux系统中病毒怎么解决 1)最简单有效的方法就是重装系统 2)要查的话就是找到病毒文件然后删除 中毒之后一般机器cpu、内存使用率会比较高 机器向外发包等异常情况,排查方法简单介绍下 top 命令找到cpu使用率最高的进程 一般病毒文件命名都比较乱,可以用 ps aux 找到病毒文件位置 rm -f 命令删除病毒文件 检查计划任务、开机启动项和病毒文件目录有无其他可以文件等 3)由于即使删除病毒文件不排除有潜伏病毒,所以最好是把机器备份数据之后重装一下 29、发现一个病毒文件你删了他又自动创建怎么解决 公司的内网某台linux服务器流量莫名其妙的剧增,用iftop查看有连接外网的情况 针对这种情况一般重点查看netstat连接的外网ip和端口。 用lsof -p pid可以查看到具体是那些进程,哪些文件 经查勘发现/root下有相关的配置conf.n hhe两个可疑文件,rm -rf后不到一分钟就自动生成了 由此推断是某个母进程产生的这些文件。所以找到母进程就是找到罪魁祸首 查杀病毒最好断掉外网访问,还好是内网服务器,可以通过内网访问 断了内网,病毒就失去外联的能力,杀掉它就容易的多 怎么找到呢,找了半天也没有看到蛛丝马迹,没办法只有ps axu一个个排查 方法是查看可以的用户和和系统相似而又不是的冒牌货,果然,看到了如下进程可疑 看不到图片就是/usr/bin/.sshd 于是我杀掉所有.sshd相关的进程,然后直接删掉.sshd这个可执行文件 然后才删掉了文章开头提到的自动复活的文件 总结一下,遇到这种问题,如果不是太严重,尽量不要重装系统 一般就是先断外网,然后利用iftop,ps,netstat,chattr,lsof,pstree这些工具顺藤摸瓜 一般都能找到元凶。但是如果遇到诸如此类的问题 /boot/efi/EFI/redhat/grub.efi: Heuristics.Broken.Executable FOUND,个人觉得就要重装系统了 30、说说TCP/IP的七层模型 应用层 (Application): 网络服务与最终用户的一个接口。 协议有:HTTP FTP TFTP SMTP SNMP DNS TELNET HTTPS POP3 DHCP 表示层(Presentation Layer): 数据的表示、安全、压缩。(在五层模型里面已经合并到了应用层) 格式有,JPEG、ASCll、DECOIC、加密格式等 会话层(Session Layer): 建立、管理、终止会话。(在五层模型里面已经合并到了应用层) 对应主机进程,指本地主机与远程主机正在进行的会话 传输层 (Transport): 定义传输数据的协议端口号,以及流控和差错校验。 协议有:TCP UDP,数据包一旦离开网卡即进入网络传输层 网络层 (Network): 进行逻辑地址寻址,实现不同网络之间的路径选择。 协议有:ICMP IGMP IP(IPV4 IPV6) ARP RARP 数据链路层 (Link): 建立逻辑连接、进行硬件地址寻址、差错校验等功能。(由底层网络定义协议) 将比特组合成字节进而组合成帧,用MAC地址访问介质,错误发现但不能纠正 物理层(Physical Layer): 是计算机网络OSI模型中最低的一层 物理层规定:为传输数据所需要的物理链路创建、维持、拆除 而提供具有机械的,电子的,功能的和规范的特性 简单的说,物理层确保原始的数据可在各种物理媒体上传输。局域网与广域网皆属第1、2层 物理层是OSI的第一层,它虽然处于最底层,却是整个开放系统的基础 物理层为设备之间的数据通信提供传输媒体及互连设备,为数据传输提供可靠的环境 如果您想要用尽量少的词来记住这个第一层,那就是“信号和介质” 31、你常用的Nginx模块,用来做什么 rewrite模块,实现重写功能 access模块:来源控制 ssl模块:安全加密 ngx_http_gzip_module:网络传输压缩模块 ngx_http_proxy_module 模块实现代理 ngx_http_upstream_module模块实现定义后端服务器列表 ngx_cache_purge实现缓存清除功能 32、请列出你了解的web服务器负载架构 Nginx Haproxy Keepalived LVS 33、查看http的并发请求数与其TCP连接状态 netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}' 还有ulimit -n 查看linux系统打开最大的文件描述符,这里默认1024 不修改这里web服务器修改再大也没用,若要用就修改很几个办法,这里说其中一个: 修改/etc/security/limits.conf soft nofile 10240 hard nofile 10240 重启后生效 34、用tcpdump嗅探80端口的访问看看谁最高 tcpdump -i eth0 -tnn dst port 80 -c 1000 | awk -F"." '{print $1"."$2"."$3"."$4}'| sort | uniq -c | sort -nr |head -20 35、写一个脚本,实现判断192.168.1.0/24网络里,当前在线的IP有哪些,能ping通则认为在线 #!/bin/bash for ip inseq 1 255 do { ping -c 1 192.168.1.$ip > /dev/null 2>&1 if [ $? -eq 0 ]; then echo 192.168.1.$ip UP else echo 192.168.1.$ip DOWN fi }& done wait 36、已知 apache 服务的访问日志按天记录在服务器本地目录/app/logs 下,由于磁盘空间紧张现在要求只能保留最近 7 天的访问日志!请问如何解决? 请给出解决办法或配置或处理命令 创建文件脚本: #!/bin/bash for n inseq 14 do date -s "11/0$n/14" touch accesswww(date +%F).log done 解决方法: pwd/application/logs ll -rw-r--r--. 1 root root 0 Jan 1 00:00 access_www_2015-01-01.log -rw-r--r--. 1 root root 0 Jan 2 00:00 access_www_2015-01-02.log -rw-r--r--. 1 root root 0 Jan 3 00:00 access_www_2015-01-03.log -rw-r--r--. 1 root root 0 Jan 4 00:00 access_www_2015-01-04.log -rw-r--r--. 1 root root 0 Jan 5 00:00 access_www_2015-01-05.log -rw-r--r--. 1 root root 0 Jan 6 00:00 access_www_2015-01-06.log -rw-r--r--. 1 root root 0 Jan 7 00:00 access_www_2015-01-07.log -rw-r--r--. 1 root root 0 Jan 8 00:00 access_www_2015-01-08.log -rw-r--r--. 1 root root 0 Jan 9 00:00 access_www_2015-01-09.log -rw-r--r--. 1 root root 0 Jan 10 00:00 access_www_2015-01-10.log -rw-r--r--. 1 root root 0 Jan 11 00:00 access_www_2015-01-11.log -rw-r--r--. 1 root root 0 Jan 12 00:00 access_www_2015-01-12.log -rw-r--r--. 1 root root 0 Jan 13 00:00 access_www_2015-01-13.log -rw-r--r--. 1 root root 0 Jan 14 00:00 access_www_2015-01-14.log find /application/logs/ -type f -mtime +7 -name "*.log"|xargs rm –f ##也可以使用-exec rm -f {} \;进行删除 ll -rw-r--r--. 1 root root 0 Jan 7 00:00 access_www_2015-01-07.log -rw-r--r--. 1 root root 0 Jan 8 00:00 access_www_2015-01-08.log -rw-r--r--. 1 root root 0 Jan 9 00:00 access_www_2015-01-09.log -rw-r--r--. 1 root root 0 Jan 10 00:00 access_www_2015-01-10.log -rw-r--r--. 1 root root 0 Jan 11 00:00 access_www_2015-01-11.log -rw-r--r--. 1 root root 0 Jan 12 00:00 access_www_2015-01-12.log -rw-r--r--. 1 root root 0 Jan 13 00:00 access_www_2015-01-13.log -rw-r--r--. 1 root root 0 Jan 14 00:00 access_www_2015-01-14.log 37、如何优化 Linux系统(可以不说太具体)? 不用root,添加普通用户,通过sudo授权管理 更改默认的远程连接SSH服务端口及禁止root用户远程连接 定时自动更新服务器时间 配置国内yum源 关闭selinux及iptables(iptables工作场景如果有外网IP一定要打开,高并发除外) 调整文件描述符的数量 精简开机启动服务(crond rsyslog network sshd) 内核参数优化(/etc/sysctl.conf) 更改字符集,支持中文,但建议还是用英文字符集,防止乱码 锁定关键系统文件 清空/etc/issue,去除系统及内核版本登录前的屏幕显示 38、请执行命令取出 linux 中 eth0 的 IP 地址(请用 cut,有能力者也可分别用 awk,sed 命令答) cut方法1: ifconfig eth0|sed -n '2p'|cut -d ":" -f2|cut -d " " -f1 192.168.20.130 awk方法2: ifconfig eth0|awk 'NR==2'|awk -F ":" '{print $2}'|awk '{print $1}' 192.168.20.130 awk多分隔符方法3: ifconfig eth0|awk 'NR==2'|awk -F "[: ]+" '{print $4}' 192.168.20.130 sed方法4: ifconfig eth0|sed -n '/inet addr/p'|sed -r 's#^.ddr:(.)Bc.*$#\1#g' 192.168.20.130 39、请写出下面 linux SecureCRT 命令行快捷键命令的功能? Ctrl + a Ctrl + c Ctrl + d Ctrl + e Ctrl + l Ctrl + u Ctrl + k tab Ctrl+shift+c Ctrl+shift+v 解答: Ctrl + a —->光标移动到行首 Ctrl + e —->光标移动到行尾 Ctrl + c —->终止当前程序 Ctrl + d —->如果光标前有字符则删除,没有则退出当前中断 Ctrl + l —->清屏 Ctrl + u —->剪切光标以前的字符 Ctrl + k —->剪切光标以后的字符 Ctrl + y —->复制u/k的内容 Ctrl + r —->查找最近用过的命令 tab —->命令或路径补全 Ctrl+shift+c —->复制 Ctrl+shift+v —->粘贴 40、每天晚上 12 点,打包站点目录/var/www/html 备份到/data 目录下(最好每次备份按时间生成不同的备份包) cat a.sh #/bin/bash cd /var/www/ && /bin/tar zcf /data/html-date +%m-%d%H.tar.gz html/ crontab –e 00 00* /bin/sh /root/a.sh 本文转自silence博客51CTO博客,原文链接http://blog.51cto.com/silencezone/2072531如需转载请自行联系原作者 a120518129

优秀的个人博客,低调大师

Android面试题(1)

1. 下列哪些语句关于内存回收的说明是正确的? (b ) A、 程序员必须创建一个线程来释放内存 B、 内存回收程序负责释放无用内存 C、 内存回收程序允许程序员直接释放内存 D、 内存回收程序可以在指定的时间释放内存对象 Android是Linux的内核,每一个程序都是一个独立的JAVA虚拟机,就和油汤里的油花一样互不干扰,这样充分保证了万一某个程序的JAVA虚拟机崩溃,系统依旧稳定正常运行. 而Android和传统Linux不一样的地方又在于,传统Linux在 进程活动停止后就结束了,这就类似于我们用S60和WM一 样,关闭程序,内存释放.而Android会把这些进程保留在内存里,干嘛呢?为了保证你再次激活这些进程时候启动的更快.Android会在系统需要更多内存 的时候,去释放掉那些占用内存的进程----这个活动是智能的. 2. 下面异常是属于Runtime Exception 的是(abcd)(多选) A、ArithmeticException B、IllegalArgumentException C、NullPointerException D、BufferUnderflowException A、ArithmeticException 当出现异常的运算条件时,抛出此异常。例如,一个整数“除以零”时,抛出此类的一个实例。 B、IllegalArgumentException 抛出的异常表明向方法传递了一个不合法或不正确的参数。 C、NullPointerException 空指针异常 D、BufferUnderflowException (不明白,没碰到过) 编码问题导致java_BufferUnderflowException异常 公共类BufferUnderflowException的延伸的RuntimeException未经检查的异常时,抛出一个相对get操作达到源缓冲区的限制。 3. Math.round(11.5)等于多少(). Math.round(-11.5)等于多少(c). A、11 ,-11 B、11 ,-12 C、12 ,-11 D、12 ,-12 四舍五入 四和五是指正的4,5 -11.5 这么看 -11.5 = -12 +0.5 ,0.5按四舍五入为1 ,-12+1 = -11,所以Math.round(-11.5)==-11 -0.5 = -1 + 0.5 0.5按四舍五入为1 ,-1+1 = 0,所以Math.round(-0.5)==0 11.5 四舍五入 显然 Math.round(11.5)==12 round方法返回与参数最接近的长整数,参数加0.5后求其floor(小于等于该数的最大整数) 4. 下列程序段的输出结果是:(b) void complicatedexpression_r(){ int x=20, y=30; boolean b; b=x>50&&y>60||x>50&&y<-60||x<-50&&y>60||x<-50&&y<-60; System.out.println(b); } A、true B、false C、1 D、0 &&(与)的优先级比||(或)高 5. 对一些资源以及状态的操作保存,最好是保存在生命周期的哪个函数中进行(a) A、onPause() B、onCreate() C、 onResume() D、onStart() 6. Intent传递数据时,下列的数据类型哪些可以被传递(abcd)(多选) A、Serializable B、charsequence C、Parcelable D、Bundle 7. android 中下列属于Intent的作用的是(c) A、实现应用程序间的数据共享 B、是一段长的生命周期,没有用户界面的程序,可以保持应用在后台运行,而不会因为切换页面而消失 C、可以实现界面间的切换,可以包含动作和动作数据,连接四大组件的纽带 D、处理一个应用程序整体性的工作 8. 下列属于SAX解析xml文件的优点的是(b) A、将整个文档树在内存中,便于操作,支持删除,修改,重新排列等多种功能(dom解析优点) B、不用事先调入整个文档,占用资源少(sax解析优点) C、整个文档调入内存,浪费时间和空间(dom解析缺点) D、不是长久驻留在内存,数据不是持久的,事件过后,若没有保存数据,数据就会(sax解析缺点)消失 不需要像dom解析那样在内存中建立一个dom对象,占用内存,sax解析是逐行解析的,每次读入内存的只是一行xml,所以速度快,效率高点。不过sax一般是处理固定格式的xml。 9. 下面的对自定style的方式正确的是(a) A、 <resources> <style name="myStyle"> <item name="android:layout_width">fill_parent</item> </style> </resources> B、 <style name="myStyle"> <item name="android:layout_width">fill_parent</item> (没有<resources> ) </style> C、 <resources> <item name="android:layout_width">fill_parent</item> (没有</style> ) </resources> D、 <resources> <style name="android:layout_width">fill_parent</style> (</style>应为</item> ) </resources> 10. 在android中使用Menu时可能需要重写的方法有(ac)。(多选) A、onCreateOptionsMenu() B、onCreateMenu() C、onOptionsItemSelected() D、onItemSelected() 11. 在SQL Server Management Studio 中运行下列T-SQL语句,其输出值(c)。 SELECT @@IDENTITY A、可能为0.1 B、可能为3 C、 不可能为-100 D、肯定为0 @@identity是表示的是最近一次向具有identity属性(即自增列)的表插入数据时对应的自增列的值,是系统定义的全局变量。一般系统定义的全局变量都是以@@开头,用户自定义变量以@开头。比如有个表A,它的自增列是id,当向A表插入一行数据后,如果插入数据后自增列的值自动增加至101,则通过select @@identity得到的值就是101。使用@@identity的前提是在进行insert操作后,执行select @@identity的时候连接没有关闭,否则得到的将是NULL值。 12. 在SQL Server 2005中运行如下T-SQL语句,假定SALES表中有多行数据,执行查询之后的结果是(d)。 BEGIN TRANSACTION A Update SALES Set qty=30 WHERE qty<30 BEGIN TRANSACTION B Update SALES Set qty=40 WHERE qty<40 Update SALES Set qty=50 WHERE qty<50 Update SALES Set qty=60 WHERE qty<60 COMMIT TRANSACTION B COMMIT TRANSACTION A A、SALES表中qty列最小值大于等于30 B、SALES表中qty列最小值大于等于40 C、SALES表中qty列的数据全部为50 D、SALES表中qty列最小值大于等于60 Update SALES Set qty=60 WHERE qty<60(关键在最后一句,执行完数据就都是大于等于60了) 13. 在android中使用SQLiteOpenHelper这个辅助类时,可以生成一个数据库,并可以对数据库版本进行管理的方法可以是(ab) A、getWriteableDatabase() B、getReadableDatabase() C、getDatabase() D、getAbleDatabase() 14. android 关于service生命周期的onCreate()和onStart()说法正确的是(ad)(多选题) A、当第一次启动的时候先后调用onCreate()和onStart()方法 B、当第一次启动的时候只会调用onCreate()方法 C、如果service已经启动,将先后调用onCreate()和onStart()方法 D、如果service已经启动,只会执行onStart()方法,不在执行onCreate()方法 15. 下面是属于GLSurFaceView特性的是(abc)(多选) A、管理一个surface,这个surface就是一块特殊的内存,能直接排版到android的视图view上。 B、管理一个EGL display,它能让opengl把内容渲染到上述的surface上。 C、让渲染器在独立的线程里运作,和UI线程分离。 D、可以直接从内存或者DMA等硬件接口取得图像数据 GLSurfaceView是一个视图,继承至SurfaceView,它内嵌的surface专门负责OpenGL渲染。 GLSurfaceView提供了下列特性: 1> 管理一个surface,这个surface就是一块特殊的内存,能直接排版到android的视图view上。 2> 管理一个EGL display,它能让opengl把内容渲染到上述的surface上。 3> 用户自定义渲染器(render)。 4> 让渲染器在独立的线程里运作,和UI线程分离。 5> 支持按需渲染(on-demand)和连续渲染(continuous)。 6> 一些可选工具,如调试。 16. 下面在AndroidManifest.xml文件中注册BroadcastReceiver方式正确的(a) A、 <receiver android:name="NewBroad"> <intent-filter> <action android:name="android.provider.action.NewBroad"/> <action> </intent-filter> </receiver> B、 <receiver android:name="NewBroad"> <intent-filter> android:name="android.provider.action.NewBroad"/> </intent-filter> </receiver> C、 <receiver android:name="NewBroad"> <action android:name="android.provider.action.NewBroad"/> <action> </receiver> D、 <intent-filter> <receiver android:name="NewBroad"> <action> android:name="android.provider.action.NewBroad"/> <action> </receiver> </intent-filter> 17. 关于ContenValues类说法正确的是(a) A、他和Hashtable比较类似,也是负责存储一些名值对,但是他存储的名值对当中的名是String类型,而值都是基本类型 B、他和Hashtable比较类似,也是负责存储一些名值对,但是他存储的名值对当中的名是任意类型,而值都是基本类型 C、他和Hashtable比较类似,也是负责存储一些名值对,但是他存储的名值对当中的名,可以为空,而值都是String类型 D、他和Hashtable比较类似,也是负责存储一些名值对,但是他存储的名值对当中的名是String类型,而值也是String类型 18. 我们都知道Hanlder是线程与Activity通信的桥梁,如果线程处理不当,你的机器就会变得越慢,那么线程销毁的方法是(a) A、onDestroy() B、onClear() C、onFinish() D、onStop() 19. 下面退出Activity错误的方法是(c) A、finish() B、抛异常强制退出 C、System.exit() D、onStop() System.exit(0) 0是正常退出 ,其他数字是表示不正常退出 20. 下面属于android的动画分类的有(ab)(多项) A、Tween B、Frame C、Draw D、Animation Animation主要有两种动画模式: 一种是tweened animation(渐变动画)一种是frame by frame(画面转换动画) XML中 JavaCodeXML中 JavaCode alpha AlphaAnimationtranslate TranslateAnimation scale ScaleAnimationrotate RotateAnimation 21. 下面关于Android dvm的进程和Linux的进程,应用程序的进程说法正确的是(d) A、DVM指dalivk的虚拟机.每一个Android应用程序都在它自己的进程中运行,不一定拥有一个独立的Dalvik虚拟机实例.而每一个DVM都是在Linux 中的一个进程,所以说可以认为是同一个概念. B、DVM指dalivk的虚拟机.每一个Android应用程序都在它自己的进程中运行,不一定拥有一个独立的Dalvik虚拟机实例.而每一个DVM不一定都是在Linux 中的一个进程,所以说不是一个概念. C、DVM指dalivk的虚拟机.每一个Android应用程序都在它自己的进程中运行,都拥有一个独立的Dalvik虚拟机实例.而每一个DVM不一定都是在Linux 中的一个进程,所以说不是一个概念. D、DVM指dalivk的虚拟机.每一个Android应用程序都在它自己的进程中运行,都拥有一个独立的Dalvik虚拟机实例.而每一个DVM都是在Linux 中的一个进程,所以说可以认为是同一个概念. 22. Android项目工程下面的assets目录的作用是什么(b) A、放置应用到的图片资源。 B、主要放置多媒体等数据文件 C、放置字符串,颜色,数组等常量数据 D、放置一些与UI相应的布局文件,都是xml文件 23. 关于res/raw目录说法正确的是(a) A、 这里的文件是原封不动的存储到设备上不会转换为二进制的格式 B、 这里的文件是原封不动的存储到设备上会转换为二进制的格式 C、 这里的文件最终以二进制的格式存储到指定的包中 D、 这里的文件最终不会以二进制的格式存储到指定的包中 24. 下列对android NDK的理解正确的是(abcd) A、 NDK是一系列工具的集合 B、 NDK 提供了一份稳定、功能有限的 API 头文件声明。 C、 使 “Java+C” 的开发方式终于转正,成为官方支持的开发方式 D、 NDK 将是 Android 平台支持 C 开发的开端 25. android中常用的四个布局是LinearLayout(线性布局)、FrameLayout(单帧布局)、RelativeLayout(相对布局)和TableLayout(表格布局)。 26. android 的四大组件是activity,service,broadcast和Content Provider。 27. java.io包中的objectinputstream和objectoutputstream类主要用于对对象(Object)的读写。 28. android 中service的实现方法是:startservice和bindservice。 Service的生命周期方法比Activity少一些,只有onCreate, onStart, onDestroy 。我们有两种方式启动一个Service,他们对Service生命周期的影响是不一样的。 1 通过startService Service会经历 onCreate --> onStart stopService的时候直接onDestroy 如果是 调用者 直接退出而没有调用stopService的话,Service会一直在后台运行。 下次调用者再起来仍然可以stopService。 2 通过bindService Service只会运行onCreate, 这个时候 调用者和Service绑定在一起 调用者退出了,Srevice就会调用onUnbind-->onDestroyed 所谓绑定在一起就共存亡了。 1. Started Service中使用StartService()方法来进行方法的调用,调用者和服务之间没有联系,即使调用者退出了,服务依然在进行【onCreate()- >onStartCommand()->startService()->onDestroy()】,注意其中没有onStart(),主要是被onStartCommand()方法给取代了,onStart方法不推荐使用了。 2. BindService中使用bindService()方法来绑定服务,调用者和绑定者绑在一起,调用者一旦退出服务也就终止了【onCreate()->onBind()->onUnbind()->onDestroy()】。 29. activity一般会重载7个方法用来维护其生命周期,除了onCreate(),onStart(),onDestory() 外还有onrestart,onresume,onpause,onstop。 30. android的数据存储的方式sharedpreference,文件,SQlite,contentprovider,网络。 31. 当启动一个Activity并且新的Activity执行完后需要返回到启动它的Activity来执行 的回调函数是startActivityForResult startActivityForResult(Intent,requestCode)//启动一个activity包含参数请求码和具体的intent数据,其中请求码可以用来识别子活动。 32. 请使用命令行的方式创建一个名字为myAvd,sdk版本为2.2,sd卡是在d盘的根目录下,名字为scard.img, 并指定屏幕大小HVGA.________________android create acd -n myAvd -t 8 -s HVDA – C d:\card.img____________________。 33. 程序运行的结果是:_____good and gbc__________。 public class Example{ String str=new String("good"); char[]ch={'a','b','c'}; public static void main(String args[]){ Example ex=new Example(); ex.change(ex.str,ex.ch); System.out.print(ex.str+" and "); Sytem.out.print(ex.ch); } public void change(String str,char ch[]){ str="test ok"; ch[0]='g'; } } 34. 在android中,请简述jni的调用过程。 1)安装和下载Cygwin,下载 Android NDK 2)在ndk项目中JNI接口的设计 3)使用C/C++实现本地方法 4)JNI生成动态链接库.so文件 5)将动态链接库复制到java工程,在java工程中调用,运行java工程即可 35. 简述Android应用程序结构是哪些? Android应用程序结构是: Linux Kernel(Linux内核)、Libraries(系统运行库或者是c/c++核心库)、Application Framework(开发框架包)、Applications(核心应用程序) 36. 请继承SQLiteOpenHelper实现: 1).创建一个版本为1的“diaryOpenHelper.db”的数据库, 2).同时创建一个 “diary” 表(包含一个_id主键并自增长,topic字符型100长度, content字符型1000长度) 3).在数据库版本变化时请删除diary表,并重新创建出diary表。 public class DBHelper extends SQLiteOpenHelper { public final static String DATABASENAME = "diaryOpenHelper.db"; public final static int DATABASEVERSION = 1; //创建数据库 public DBHelper(Context context,String name,CursorFactory factory,int version){ super(context, name, factory, version); } //创建表等机构性文件 public void onCreate(SQLiteDatabase db){ String sql ="create table diary"+"("+"_id integer primary key autoincrement,"+"topic varchar(100),"+"content varchar(1000)"+")"; db.execSQL(sql); } //若数据库版本有更新,则调用此方法 public void onUpgrade(SQLiteDatabase db,int oldVersion,int newVersion){ String sql = "drop table if exists diary"; db.execSQL(sql); this.onCreate(db); } } 37. 页面上现有ProgressBar控件progressBar,请用书写线程以10秒的的时间完成其进度显示工作。 public class ProgressBarStu extends Activity { private ProgressBar progressBar = null; protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.progressbar); //从这到下是关键 progressBar = (ProgressBar)findViewById(R.id.progressBar); Thread thread = new Thread(new Runnable() { @Override public void run() { int progressBarMax = progressBar.getMax(); try { while(progressBarMax!=progressBar.getProgress()){ int stepProgress = progressBarMax/10; int currentprogress = progressBar.getProgress(); progressBar.setProgress(currentprogress+stepProgress); Thread.sleep(1000); } } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }); thread.start(); //关键结束 } } 38. 请描述下Activity的生命周期。 必调用的三个方法:onCreate() --> onStart() --> onResume(),用AAA表示 (1)父Activity启动子Activity,子Actvity退出,父Activity调用顺序如下AAA --> onPause() --> onStop() --> onRestart() --> onStart(),onResume() … (2)用户点击Home,Actvity调用顺序如下AAA --> onPause() --> onStop() -- Maybe --> onDestroy() – Maybe(3)调用finish(), Activity调用顺序如下AAA --> onPause() --> onStop() --> onDestroy() (4)在父Activity上显示透明的或非全屏的activity,Activity调用顺序如下AAA --> onPause() (5)设备进入睡眠状态,Activity调用顺序如下AAA --> onPause() 39. 如果后台的Activity由于某原因被系统回收了,如何在被系统回收之前保存当前状态? onSaveInstanceState() 当你的程序中某一个Activity A在运行时,主动或被动地运行另一个新的Activity B,这个时候A会执行onSaveInstanceState()。B完成以后又会来找A,这个时候就有两种情况:一是A被回收,二是A没有被回收,被回收的A就要重新调用onCreate()方法,不同于直接启动的是这回onCreate()里是带上了参数savedInstanceState;而没被收回的就直接执行onResume(),跳过onCreate()了。 40. 如何将一个Activity设置成窗口的样式。 在AndroidManifest.xml 中定义Activity的地方一句话 android:theme="@android:style/Theme.Dialog"或android:theme="@android:style/Theme.Translucent" 就变成半透明的 41. 如何退出Activity?如何安全退出已调用多个Activity的Application? 对于单一Activity的应用来说,退出很简单,直接finish()即可。当然,也可以用killProcess()和System.exit()这样的方法。 对于多个: 1、抛异常强制退出: 该方法通过抛异常,使程序Force Close。验证可以,但是,需要解决的问题是,如何使程序结束掉,而不弹出Force Close的窗口。 2、记录打开的Activity: 每打开一个Activity,就记录下来。在需要退出时,关闭每一个Activity即可。 3、发送特定广播: 在需要结束应用时,发送一个特定的广播,每个Activity收到广播后,关闭即可。 4、递归退出 在打开新的Activity时使用startActivityForResult,然后自己加标志,在onActivityResult中处理,递归关闭。 42. 请介绍下Android中常用的五种布局。 FrameLayout(框架布局),LinearLayout (线性布局),AbsoluteLayout(绝对布局),RelativeLayout(相对布局),TableLayout(表格布局) 43. 请介绍下Android的数据存储方式。 一.SharedPreferences方式 二.文件存储方式 三.SQLite数据库方式 四.内容提供器(Content provider)方式 五. 网络存储方式 44. 请介绍下ContentProvider是如何实现数据共享的。 创建一个属于你自己的Content provider或者将你的数据添加到一个已经存在的Content provider中,前提是有相同数据类型并且有写入Content provider的权限。 45. 如何启用Service,如何停用Service。 Android中的service类似于windows中的service,service一般没有用户操作界面,它运行于系统中不容易被用户发觉,可以使用它开发如监控之类的程序。 一、步骤 第一步:继承Service类 public class SMSService extends Service { } 第二步:在AndroidManifest.xml文件中的<application>节点里对服务进行配置: <service android:name=".DemoService" /> 二、Context.startService()和Context.bindService 服务不能自己运行,需要通过调用Context.startService()或Context.bindService()方法启动服务。这两个方法都可以启动Service,但是它们的使用场合有所不同。 1.使用startService()方法启用服务,调用者与服务之间没有关连,即使调用者退出了,服务仍然运行。使用bindService()方法启用服务,调用者与服务绑定在了一起,调用者一旦退出,服务也就终止。 2.采用Context.startService()方法启动服务,在服务未被创建时,系统会先调用服务的onCreate()方法,接着调用onStart()方法。如果调用startService()方法前服务已经被创建,多次调用startService()方法并不会导致多次创建服务,但会导致多次调用onStart()方法。采用startService()方法启动的服务,只能调用Context.stopService()方法结束服务,服务结束时会调用onDestroy()方法。 3.采用Context.bindService()方法启动服务,在服务未被创建时,系统会先调用服务的onCreate()方法,接着调用onBind()方法。这个时候调用者和服务绑定在一起,调用者退出了,系统就会先调用服务的onUnbind()方法,。接着调用onDestroy()方法。如果调用bindService()方法前服务已经被绑定,多次调用bindService()方法并不会导致多次创建服务及绑定(也就是说onCreate()和onBind()方法并不会被多次调用)。如果调用者希望与正在绑定的服务解除绑定,可以调用unbindService()方法,调用该方法也会导致系统调用服务的onUnbind()-->onDestroy()方法。 三、Service的生命周期 1.Service常用生命周期回调方法如下: onCreate() 该方法在服务被创建时调用,该方法只会被调用一次,无论调用多少次startService()或bindService()方法,服务也只被创建一次。 onDestroy()该方法在服务被终止时调用。 2. Context.startService()启动Service有关的生命周期方法onStart() 只有采用Context.startService()方法启动服务时才会回调该方法。该方法在服务开始运行时被调用。多次调用startService()方法尽管不会多次创建服务,但onStart() 方法会被多次调用。 3. Context.bindService()启动Service有关的生命周期方法onBind()只有采用Context.bindService()方法启动服务时才会回调该方法。该方法在调用者与服务绑定时被调用,当调用者与服务已经绑定,多次调用Context.bindService()方法并不会导致该方法被多次调用。onUnbind()只有采用Context.bindService()方法启动服务时才会回调该方法。该方法在调用者与服务解除绑定时被调用。 备注: 1. 采用startService()启动服务 Intent intent =newIntent(DemoActivity.this, DemoService.class ); startService(intent); 2.Context.bindService()启动 Intent intent =newIntent(DemoActivity.this, DemoService.class ); bindService(intent, conn, Context.BIND_AUTO_CREATE);//unbindService(conn);//解除绑定 46. 注册广播有几种方式,这些方式有何优缺点?请谈谈Android引入广播机制的用意。 Android广播机制(两种注册方法) 在android下,要想接受广播信息,那么这个广播接收器就得我们自己来实现了,我们可以继承BroadcastReceiver,就可以有一个广播接受器了。有个接受器还不够,我们还得重写BroadcastReceiver里面的onReceiver方法,当来广播的时候我们要干什么,这就要我们自己来实现,不过我们可以搞一个信息防火墙。具体的代码: public class SmsBroadCastReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent){ Bundle bundle = intent.getExtras(); Object[] object = (Object[])bundle.get("pdus"); SmsMessage sms[]=new SmsMessage[object.length]; for(int i=0;i<object.length;i++){ sms[0] = SmsMessage.createFromPdu((byte[])object[i]); Toast.makeText(context, "来自"+sms[i].getDisplayOriginatingAddress()+" 的消息是:"+sms[i].getDisplayMessageBody(), Toast.LENGTH_SHORT).show(); } //终止广播,在这里我们可以稍微处理,根据用户输入的号码可以实现短信防火墙。 abortBroadcast(); } } 当实现了广播接收器,还要设置广播接收器接收广播信息的类型,这里是信息:android.provider.Telephony.SMS_RECEIVED 我们就可以把广播接收器注册到系统里面,可以让系统知道我们有个广播接收器。这里有两种,一种是代码动态注册: //生成广播处理 smsBroadCastReceiver = new SmsBroadCastReceiver(); //实例化过滤器并设置要过滤的广播 IntentFilter intentFilter = new IntentFilter("android.provider.Telephony.SMS_RECEIVED"); //注册广播 BroadCastReceiverActivity.this.registerReceiver(smsBroadCastReceiver, intentFilter); 一种是在AndroidManifest.xml中配置广播 <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="spl.broadCastReceiver" android:versionCode="1" android:versionName="1.0"> <application android:icon="@drawable/icon" android:label="@string/app_name"> <activity android:name=".BroadCastReceiverActivity" android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <!--广播注册--> <receiver android:name=".SmsBroadCastReceiver"> <intent-filter android:priority="20"> <action android:name="android.provider.Telephony.SMS_RECEIVED"/> </intent-filter> </receiver> </application> <uses-sdk android:minSdkVersion="7" /> <!-- 权限申请 --> <uses-permission android:name="android.permission.RECEIVE_SMS"></uses-permission> </manifest> 两种注册类型的区别是: 1)第一种不是常驻型广播,也就是说广播跟随程序的生命周期。 2)第二种是常驻型,也就是说当应用程序关闭后,如果有信息广播来,程序也会被系统调用自动运行。 47. 请解释下在单线程模型中Message、Handler、Message Queue、Looper之间的关系。 Handler简介: 一个Handler允许你发送和处理Message和Runable对象,这些对象和一个线程的MessageQueue相关联。每一个线程实例和一个单独的线程以及该线程的MessageQueue相关联。当你创建一个新的Handler时,它就和创建它的线程绑定在一起了。这里,线程我们也可以理解为线程的MessageQueue。从这一点上来看,Handler把Message和Runable对象传递给MessageQueue,而且在这些对象离开MessageQueue时,Handler负责执行他们。 Handler有两个主要的用途:(1)确定在将来的某个时间点执行一个或者一些Message和Runnable对象。(2)在其他线程(不是Handler绑定线程)中排入一些要执行的动作。 Scheduling Message,即(1),可以通过以下方法完成: post(Runnable):Runnable在handler绑定的线程上执行,也就是说不创建新线程。 postAtTime(Runnable,long): postDelayed(Runnable,long): sendEmptyMessage(int): sendMessage(Message): sendMessageAtTime(Message,long): sendMessageDelayed(Message,long): post这个动作让你把Runnable对象排入MessageQueue,MessageQueue受到这些消息的时候执行他们,当然以一定的排序。sendMessage这个动作允许你把Message对象排成队列,这些Message对象包含一些信息,Handler的hanlerMessage(Message)会处理这些Message.当然,handlerMessage(Message)必须由Handler的子类来重写。这是编程人员需要作的事。 当posting或者sending到一个Hanler时,你可以有三种行为:当MessageQueue准备好就处理,定义一个延迟时间,定义一个精确的时间去处理。后两者允许你实现timeout,tick,和基于时间的行为。 当你的应用创建一个新的进程时,主线程(也就是UI线程)自带一个MessageQueue,这个MessageQueue管理顶层的应用对象(像activities,broadcast receivers等)和主线程创建的窗体。你可以创建自己的线程,并通过一个Handler和主线程进行通信。这和之前一样,通过post和sendmessage来完成,差别在于在哪一个线程中执行这么方法。在恰当的时候,给定的Runnable和Message将在Handler的MessageQueue中被Scheduled。 Message简介: Message类就是定义了一个信息,这个信息中包含一个描述符和任意的数据对象,这个信息被用来传递给Handler.Message对象提供额外的两个int域和一个Object域,这可以让你在大多数情况下不用作分配的动作。 尽管Message的构造函数是public的,但是获取Message实例的最好方法是调用Message.obtain(),或者Handler.obtainMessage()方法,这些方法会从回收对象池中获取一个。 MessageQueue简介: 这是一个包含message列表的底层类。Looper负责分发这些message。Messages并不是直接加到一个MessageQueue中,而是通过MessageQueue.IdleHandler关联到Looper。 你可以通过Looper.myQueue()从当前线程中获取MessageQueue。 Looper简介: Looper类被用来执行一个线程中的message循环。默认情况,没有一个消息循环关联到线程。在线程中调用prepare()创建一个Looper,然后用loop()来处理messages,直到循环终止。 大多数和message loop的交互是通过Handler。 下面是一个典型的带有Looper的线程实现。 class LooperThread extends Thread { public Handler mHandler; public void run() { Looper.prepare(); mHandler = new Handler() { public void handleMessage(Message msg) { // process incoming messages here } }; Looper.loop(); } } 48. AIDL的全称是什么?如何工作?能处理哪些类型的数据? AIDL的英文全称是Android Interface Define Language 当A进程要去调用B进程中的service时,并实现通信,我们通常都是通过AIDL来操作的 A工程: 首先我们在com.yydcdut.mobile.aidlservice包中创建一个RemoteService.aidl文件,在里面我们自定义一个接口,含有方法get。ADT插件会在gen目录下自动生成一个RemoteService.java文件,该类中含有一个名为RemoteService.stub的内部类,该内部类中含有aidl文件接口的get方法。 说明一:aidl文件的位置不固定,可以任意 然后定义自己的MyService类,在MyService类中自定义一个内部类去继承RemoteService.stub这个内部类,实现get方法。在onBind方法中返回这个内部类的对象,系统会自动将这个对象封装成IBinder对象,传递给他的调用者。 其次需要在AndroidManifest.xml文件中配置MyService类,代码如下: <!-- 注册服务 --> <service android:name=".MyService"> <intent-filter> <!-- 指定调用AIDL服务的ID --> <action android:name="net.blogjava.mobile.aidlservice.RemoteService" /> </intent-filter> </service> 为什么要指定调用AIDL服务的ID,就是要告诉外界MyService这个类能够被别的进程访问,只要别的进程知道这个ID,正是有了这个ID,B工程才能找到A工程实现通信。 说明:AIDL并不需要权限 B工程: 首先我们要将A工程中生成的RemoteService.java文件拷贝到B工程中,在bindService方法中绑定aidl服务 绑定AIDL服务就是将RemoteService的ID作为intent的action参数。 说明:如果我们单独将RemoteService.aidl文件放在一个包里,那个在我们将gen目录下的该包拷贝到B工程中。如果我们将RemoteService.aidl文件和我们的其他类存放在一起,那么我们在B工程中就要建立相应的包,以保证RmoteService.java文件的报名正确,我们不能修改RemoteService.java文件 bindService(new Inten("net.blogjava.mobile.aidlservice.RemoteService"), serviceConnection, Context.BIND_AUTO_CREATE); ServiceConnection的onServiceConnected(ComponentName name, IBinder service)方法中的service参数就是A工程中MyService类中继承了RemoteService.stub类的内部类的对象。 49. 请解释下Android程序运行时权限与文件系统权限的区别。 运行时权限Dalvik( android授权) 文件系统 linux 内核授权 50. 系统上安装了多种浏览器,能否指定某浏览器访问指定页面?请说明原由。 通过直接发送Uri把参数带过去,或者通过manifest里的intentfilter里的data属性 51. 你如何评价Android系统?优缺点。 优点:开放性、挣脱运营商的束缚、丰富的硬件选择、不受任何限制的开发商、无缝结合的Google应用 不足:安全和隐私 、首先开卖Android手机的不是最大运营商 、运营商仍然能够影响到Android手机、同类机型用户减少、过分依赖开发商缺少标准配置 52. 什么是ANR 如何避免它? 答:ANR:Application Not Responding,五秒 在Android中,活动管理器和窗口管理器这两个系统服务负责监视应用程序的响应。当出现下列情况时,Android就会显示ANR对话框了: 对输入事件(如按键、触摸屏事件)的响应超过5秒 意向接受器(intentReceiver)超过10秒钟仍未执行完毕 Android应用程序完全运行在一个独立的线程中(例如main)。这就意味着,任何在主线程中运行的,需要消耗大量时间的操作都会引发ANR。因为此时,你的应用程序已经没有机会去响应输入事件和意向广播(Intent broadcast)。 因此,任何运行在主线程中的方法,都要尽可能的只做少量的工作。特别是活动生命周期中的重要方法如onCreate()和 onResume()等更应如此。潜在的比较耗时的操作,如访问网络和数据库;或者是开销很大的计算,比如改变位图的大小,需要在一个单独的子线程中完成(或者是使用异步请求,如数据库操作)。但这并不意味着你的主线程需要进入阻塞状态已等待子线程结束 -- 也不需要调用Therad.wait()或者Thread.sleep()方法。取而代之的是,主线程为子线程提供一个句柄(Handler),让子线程在即将结束的时候调用它(xing:可以参看Snake的例子,这种方法与以前我们所接触的有所不同)。使用这种方法涉及你的应用程序,能够保证你的程序对输入保持良好的响应,从而避免因为输入事件超过5秒钟不被处理而产生的ANR。这种实践需要应用到所有显示用户界面的线程,因为他们都面临着同样的超时问题。 53. 什么情况会导致Force Close ?如何避免?能否捕获导致其的异常? 答:一般像空指针啊,可以看起logcat,然后对应到程序中来解决错误 54. Android本身的api并未声明会抛出异常,则其在运行时有无可能抛出runtime异常,你遇到过吗?诺有的话会导致什么问题?如何解决? 答:比如空指针异常,通过try{}catch(){}捕获 55. 简要解释一下activity、 intent 、intent filter、service、Broadcase、BroadcaseReceiver 答:一个activity呈现了一个用户可以操作的可视化用户界面 一个service不包含可见的用户界面,而是在后台无限地运行,可以连接到一个正在运行的服务中,连接后,可以通过服务中暴露出来的借口与其进行通信 一个broadcast receiver是一个接收广播消息并作出回应的component,broadcast receiver没有界面 intent:content provider在接收到ContentResolver的请求时被激活。 activity, service和broadcast receiver是被称为intents的异步消息激活的。 一个intent是一个Intent对象,它保存了消息的内容。对于activity和service来说,它指定了请求的操作名称和待操作数据的URI Intent对象可以显式的指定一个目标component。如果这样的话,android会找到这个component(基于manifest文件中的声明)并激活它。但如果一个目标不是显式指定的,android必须找到响应intent的最佳component。 它是通过将Intent对象和目标的intent filter相比较来完成这一工作的。一个component的intent filter告诉android该component能处理的intent。intent filter也是在manifest文件中声明的。 56. IntentService有何优点? 答:IntentService 的好处 * Acitivity的进程,当处理Intent的时候,会产生一个对应的Service * Android的进程处理器现在会尽可能的不kill掉你 * 非常容易使用 57. 横竖屏切换时候activity的生命周期? 1、不设置Activity的android:configChanges时,切屏会重新调用各个生命周期,切横屏时会执行一次,切竖屏时会执行两次 2、设置Activity的android:configChanges="orientation"时,切屏还是会重新调用各个生命周期,切横、竖屏时只会执行一次 3、设置Activity的android:configChanges="orientation|keyboardHidden"时,切屏不会重新调用各个生命周期,只会执行onConfigurationChanged方法 58. 如何将打开res/raw目录中的数据库文件? 答:在Android中不能直接打开res/raw目录中的数据库文件,而需要在程序第一次启动时将该文件复制到手机内存或SD卡的某个目录中,然后再打开该数据库文件。复制的基本方法是使用getResources().openRawResource方法获得res/raw目录中资源的 InputStream对象,然后将该InputStream对象中的数据写入其他的目录中相应文件中。在Android SDK中可以使用SQLiteDatabase.openOrCreateDatabase方法来打开任意目录中的SQLite数据库文件。 59. Android引入广播机制的用意? 答:a:从MVC的角度考虑(应用程序内) 其实回答这个问题的时候还可以这样问,android为什么要有那4大组件,现在的移动开发模型基本上也是照搬的web那一套MVC架构,只不过是改了点嫁妆而已。android的四大组件本质上就是为了实现移动或者说嵌入式设备上的MVC架构,它们之间有时候是一种相互依存的关系,有时候又是一种补充关系,引入广播机制可以方便几大组件的信息和数据交互。 b:程序间互通消息(例如在自己的应用程序内监听系统来电) c:效率上(参考UDP的广播协议在局域网的方便性) d:设计模式上(反转控制的一种应用,类似监听者模式) 60. Android dvm的进程和Linux的进程, 应用程序的进程是否为同一个概念 DVM指dalivk的虚拟机。每一个Android应用程序都在它自己的进程中运行,都拥有一个独立的Dalvik虚拟机实例。而每一个DVM都是在Linux 中的一个进程,所以说可以认为是同一个概念。 61. sim卡的EF 文件有何作用 sim卡的文件系统有自己规范,主要是为了和手机通讯,sim本 身可以有自己的操作系统,EF就是作存储并和手机通讯用的 62. 嵌入式操作系统内存管理有哪几种,各有何特性 页式,段式,段页,用到了MMU,虚拟空间等技术 63. 什么是嵌入式实时操作系统, Android 操作系统属于实时操作系统吗? 嵌入式实时操作系统是指当外界事件或数据产生时,能够接受并以足够快的速度予以处理,其处理的结果又能在规定的时间之内来控制生产过程或对处理系统作出快速响应,并控制所有实时任务协调一致运行的嵌入式操作系统。主要用于工业控制、 军事设备、 航空航天等领域对系统的响应时间有苛刻的要求,这就需要使用实时系统。又可分为软实时和硬实时两种,而android是基于linux内核的,因此属于软实时。 64. 一条最长的短信息约占多少byte? 中文70(包括标点),英文160,160个字节。 65. android中的动画有哪几类,它们的特点和区别是什么? 两种,一种是Tween动画、还有一种是Frame动画。Tween动画,这种实现方式可以使视图组件移动、放大、缩小以及产生透明度的变化;另一种Frame动画,传统的动画方法,通过顺序的播放排列好的图片来实现,类似电影。 66. handler机制的原理 andriod提供了 Handler 和 Looper 来满足线程间的通信。Handler 先进先出原则。Looper类用来管理特定线程内对象之间的消息交换(Message Exchange)。 1)Looper: 一个线程可以产生一个Looper对象,由它来管理此线程里的Message Queue(消息队列)。 2)Handler: 你可以构造Handler对象来与Looper沟通,以便push新消息到Message Queue里;或者接收Looper从Message Queue取出)所送来的消息。 3) Message Queue(消息队列):用来存放线程放入的消息。 4)线程:UI thread 通常就是main thread,而Android启动程序时会替它建立一个Message Queue。 67. 说说mvc模式的原理,它在android中的运用 MVC(Model_view_contraller)”模型_视图_控制器”。 MVC应用程序总是由这三个部分组成。Event(事件)导致Controller改变Model或View,或者同时改变两者。只要 Controller改变了Models的数据或者属性,所有依赖的View都会自动更新。 68. DDMS和TraceView的区别? DDMS是一个程序执行查看器,在里面可以看见线程和堆栈等信息,TraceView是程序性能分析器 。 69. java中如何引用本地语言 可以用JNI(java native interface java 本地接口)接口 。 70. 谈谈Android的IPC(进程间通信)机制 IPC是内部进程通信的简称, 是共享"命名管道"的资源。Android中的IPC机制是为了让Activity和Service之间可以随时的进行交互,故在Android中该机制,只适用于Activity和Service之间的通信,类似于远程方法调用,类似于C/S模式的访问。通过定义AIDL接口文件来定义IPC接口。Servier端实现IPC接口,Client端调用IPC接口本地代理。 71. NDK是什么 NDK是一些列工具的集合,NDK提供了一系列的工具,帮助开发者迅速的开发C/C++的动态库,并能自动将so和java 应用打成apk包。 NDK集成了交叉编译器,并提供了相应的mk文件和隔离cpu、平台等的差异,开发人员只需简单的修改mk文件就可以创建出so 72. 如何将SQLite数据库(dictionary.db文件)与apk文件一起发布? 可以将dictionary.db文件复制到Eclipse Android工程中的res/raw目录中。所有在res/raw目录中的文件不会被压缩,这样可以直接提取该目录中的文件。可以将dictionary.db文件复制到res/raw目录中 本文转自我爱物联网博客园博客,原文链接:http://www.cnblogs.com/yydcdut/p/3907327.html,如需转载请自行联系原作者

优秀的个人博客,低调大师

Android面试题(2)

1.activity的生命周期 方法 描述 可被杀死 下一个 onCreate() 在activity第一次被创建的时候调用。这里是你做所有初始化设置的地方──创建视图、设置布局、绑定数据至列表等。如果曾经有状态记录(参阅后述Saving Activity State。),则调用此方法时会传入一个包含着此activity以前状态的包对象做为参数。 总继之以onStart()。 否 onStart() onRestart() 在activity停止后onStop(),在再次启动之前被调用。 总继之以onStart()。 否 onStart() onStart() 当activity正要变得为用户所见时被调用。 当activity转向前台时继以onResume(),在activity变为隐藏时继以onStop()。 否 onResume() or onStop() onResume() 在activity开始与用户进行交互之前被调用。此时activity位于堆栈顶部,并接受用户输入。 继之以onPause()。 否 onPause() onPause() 当系统将要启动另一个activity时调用。此方法主要用来将未保存的变化进行持久化,停止类似动画这样耗费CPU的动作等。这一切动作应该在短时间内完成,因为下一个activity必须等到此方法返回后才会继续。 当activity重新回到前台是继以onResume()。当activity变为用户不可见时继以onStop()。 是 onResume() or onStop() onStop() 当activity不再为用户可见时调用此方法。这可能发生在它被销毁或者另一个activity(可能是现存的或者是新的)回到运行状态并覆盖了它。 如果activity再次回到前台跟用户交互则继以onRestart(),如果关闭activity则继以onDestroy()。 是 onRestart() or onDestroy() onDestroy() 在activity销毁前调用。这是activity接收的最后一个调用。这可能发生在activity结束(调用了它的finish()方法)或者因为系统需要空间所以临时的销毁了此acitivity的实例时。你可以用isFinishing() 方法来区分这两种情况。 是 nothing 2.横竖屏切换时候activity的生命周期 1.不设置Activity的android:configChanges时,切屏会重新调用各个生命周期,切横屏时会执行一次,切竖屏时会执行两次. 2.设置Activity的android:configChanges="orientation"时,切屏还是会重新调用各个生命周期,切横、竖屏时只会执行一次. 3.设置Activity的android:configChanges="orientation|keyboardHidden"时,切屏不会重新调用各个生命周期,只会执行onConfigurationChanged方法. 3.android中线程与线程,进程与进程之间如何通信 1、一个 Android 程序开始运行时,会单独启动一个Process。 默认情况下,所有这个程序中的Activity或者Service都会跑在这个Process。 默认情况下,一个Android程序也只有一个Process,但一个Process下却可以有许多个Thread。 2、一个 Android 程序开始运行时,就有一个主线程Main Thread被创建。该线程主要负责UI界面的显示、更新和控件交互,所以又叫UI Thread。 一个Android程序创建之初,一个Process呈现的是单线程模型--即Main Thread,所有的任务都在一个线程中运行。所以,Main Thread所调用的每一个函数,其耗时应该越短越好。而对于比较费时的工作,应该设法交给子线程去做,以避免阻塞主线程(主线程被阻塞,会导致程序假死 现象)。 3、Android单线程模型:Android UI操作并不是线程安全的并且这些操作必须在UI线程中执行。如果在子线程中直接修改UI,会导致异常。 4.在android中mvc的具体体现 Android 的官方建议应用程序的开发采用MVC 模式。MVC 是Model,View,Controller 的缩写,MVC 包含三个部分: .. 模型(Model)对象:是应用程序的主体部分,所有的业务逻辑都应该写在该层。 .. 视图(View)对象:是应用程序中负责生成用户界面的部分。也是在整个MVC 架构中用户唯一可以看到的一层,接收用户的输入,显示处理结果。 .. 控制器(Control)对象:是根据用户的输入,控制用户界面数据显示及更新Model 对象状态的部分,控制器更重要的一种导航功能,想用用户出发的相关事件,交给M 哦得了处理。 Android 鼓励弱耦合和组件的重用,在Android 中MVC 的具体体现如下 1)视图层(view):一般采用xml文件进行界面的描述,使用的时候可以非常方便的引入,当然,如何你对android了解的比较的多了话,就一定可 以想到在android中也可以使用javascript+html等的方式作为view层,当然这里需要进行java和javascript之间的通 信,幸运的是,android提供了它们之间非常方便的通信实现。 2)控制层(controller):android的控制层的重 任通常落在了众多的acitvity的肩上,这句话也就暗含了不要在acitivity中写代码,要通过activity交割model业务逻辑层处理, 这样做的另外一个原因是android中的acitivity的响应时间是5s,如果耗时的操作放在这里,程序就很容易被回收掉。 3)模型层(model):对数据库的操作、对网络等的操作都应该在model里面处理,当然对业务计算等操作也是必须放在的该层的。 5.Android常用控件的信息 单选框(RadioButton与RadioGroup): RadioGroup用于对单选框进行分组,相同组内的单选框只有一个单选框被选中。 事件:setOnCheckedChangeListener(),处理单选框被选择事件。把RadioGroup.OnCheckedChangeListener实例作为参数传入。 多选框(CheckBox): 每个多选框都是独立的,可以通过迭代所有的多选框,然后根据其状态是否被选中在获取其值。 事件:setOnCheckedChangeListener(),处理多选框被选择事件。把CheckBox.OnCheckedChangeListener()实例作为参数传入。 下拉列表框(Spinner): Spinner.getItemAtPosition(Spinner.getSelectedItemPosition());获取下拉列表框的值。 事件:setOnItemSelectedListener(),处理下拉列表框被选择事件把Spinner.OnItemSelectedListener()实例作为参数传入。 拖动条(SeekBar): SeekBar.getProgress()获取拖动条当前值 事件:setOnSeekBarChangeListener(),处理拖动条值变化事件,把SeekBar.OnSeekBarChangeListener实例作为参数传入。 菜单(Menu): 重写Activity的onCreatOptionMenu(Menu menu)方法,该方法用于创建选项菜单,当用户按下手机的"Menu"按钮时就会显示创建好的菜单,在onCreatOptionMenu(Menu Menu)方法内部可以调用Menu.add()方法实现菜单的添加。 重写Activity的onMenuItemSelected()方法,该方法用于处理菜单被选择事件。 进度对话框(ProgressDialog): 创建并显示一个进度对话框:ProgressDialog.show(ProgressDialogActivity.this,"请稍等","数据正在加载中....",true); 设置对话框的风格:setProgressStyle() ProgressDialog.STYLE_SPINNER 旋转进度条风格(为默认风格) ProgressDialog.STYLE_HORIZONTAL 横向进度条风格 ①EditText(编辑框)的事件监听---OnKeyListener ②RadioGroup、RadioButton(单选按钮)的事件监听---OnCheckedChangeListener ③CheckBox(多选按钮)的事件监听---OnCheckedChangeListener ④Spinner(下拉列表)的事件监听---OnItemSelectedListener ⑤Menu(菜单)的事件处理---onMenuItemSelected ⑥Dialog(对话框)的事件监听---DialogInterface.OnClickListener() 6.请介绍下Android中常用的五种布局 Android布局是应用界面开发的重要一环,在Android中,共有五种布局方式,分别是:FrameLayout(帧布局),LinearLayout (线性布局),AbsoluteLayout(绝对布局),RelativeLayout(相对布局),TableLayout(表格布局)。 1.FrameLayout 这个布局可以看成是墙脚堆东西,有一个四方的矩形的左上角墙脚,我们放了第一个东西,要再放一个,那就在放在原来放的位置的上面,这样依次的放,会盖住原来的东西。这个布局比较简单,也只能放一点比较简单的东西。 2.LinearLayout 线性布局,这个东西,从外框上可以理解为一个div,他首先是一个一个从上往下罗列在屏幕上。每一个LinearLayout里面又可分为垂直布局 (android:orientation="vertical")和水平布局(android:orientation="horizontal" )。当垂直布局时,每一行就只有一个元素,多个元素依次垂直往下;水平布局时,只有一行,每一个元素依次向右排列。 LinearLayout中有一个重要的属性 android:layout_weight="1",这个weight在垂直布局时,代表行距;水平的时候代表列宽;weight值越大就越大。 3.AbsoluteLayout 绝对布局犹如div指定了absolute属性,用X,Y坐标来指定元素的位置android:layout_x="20px" android:layout_y="12px" 这种布局方式也比较简单,但是在垂直随便切换时,往往会出问题,而且多个元素的时候,计算比较麻烦。 4.RelativeLayout 相对布局可以理解为某一个元素为参照物,来定位的布局方式。主要属性有: 相对于某一个元素 android:layout_below="@id/aaa" 该元素在 id为aaa的下面 android:layout_toLeftOf="@id/bbb" 该元素在 id为bbb的左边 相对于父元素的地方 android:layout_alignParentLeft="true" 与父元素左对齐 android:layout_alignParentRight="true" 与父元素右对齐 还可以指定边距等,具体详见API 5.TableLayout 表格布局类似Html里面的Table。每一个TableLayout里面有表格行TableRow,TableRow里面可以具体定义每一个元素,设定他的对齐方式 android:gravity="" 。 每一个布局都有自己适合的方式,另外,这五个布局元素可以相互嵌套应用,做出美观的界面。 7.ListView的优化方案 1.如果自定义适配器,那么在getView方法中要考虑方法传进来的参数contentView是否为null,如果为null就创建contentView并返回,如果不为null则直接使用。在这个方法中,尽可能少创建view。 2.给contentView设置tag(setTag()),传入一个viewHolder对象,用于缓存要显示的数据,可以达到图像数据异步加载的效果 3.如果listview需要显示的item很多,就要考虑分页加载。比如一共要显示100条或者更多的时候,我们可以考虑先加载20条,等用户拉到列表底部的时候,再去加载接下来的20条。 8.广播接收者生命周期 广播接收器只有一个回调方法: void onReceive(Context curContext, Intent broadcastMsg) 当广播消息抵达接收器时,Android调用它的onReceive()方法并将包含消息的Intent对象传递给它。广播接收器仅在它执行这个方法时处于活跃状态。当onReceive()返回后,它即为失活状态。 拥有一个活跃状态的广播接收器的进程被保护起来而不会被杀死。但仅拥有失活状态组件的进程则会在其它进程需要它所占有的内存的时候随时被杀掉。 这种方式引出了一个问题:如果响应一个广播信息需要很长的一段时间,我们一般会将其纳入一个衍生的线程中去完成,而不是在主线程内完成它,从而保证用户交互过程的流畅。如果onReceive()衍生了一个线程并且返回,则包涵新线程在内的整个进程都被会判为失活状态(除非进程内的其它应用程序组件仍处于活跃状态),于是它就有可能被杀掉。这个问题的解决方法是令onReceive()启动一个新服务,并用其完成任务,于是系统就会知道进程中仍然在处理着工作。 9.4种activity的启动模式 standard: 标准模式,一调用startActivity()方法就会产生一个新的实例。 singleTop: 如果已经有一个实例位于Activity栈的顶部时,就不产生新的实例,而只是调用Activity中的newInstance()方法。如果不位于栈顶,会产生一个新的实例。 singleTask: 会在一个新的task中产生这个实例,以后每次调用都会使用这个,不会去产生新的实例了。 singleInstance: 这个跟singleTask基本上是一样,只有一个区别:在这个模式下的Activity实例所处的task中,只能有这个activity实例,不能有其他的实例。 10.Android Intent的使用 在一个Android应用中,主要是由一些组件组成,(Activity,Service,ContentProvider,etc.)在这些组件之间的通讯中,由Intent协助完成。 正如网上一些人解析所说,Intent负责对应用中一次操作的动作、动作涉及数据、附加数据进行描述,Android则根据此Intent的描述,负责找到对应的组件,将 Intent传递给调用的组件,并完成组件的调用。Intent在这里起着实现调用者与被调用者之间的解耦作用。 Intent传递过程中,要找到目标消费者(另一个Activity,IntentReceiver或Service),也就是Intent的响应者,有两种方法来匹配: 1,显示匹配(Explicit): public TestB extents Activity { // ......... }; public class Test extends Activity { //...... public void switchActivity() { Intent i = new Intent(Test.this, TestB.class); this.startActivity(i); } } 代码简洁明了,执行了switchActivity()函数,就会马上跳转到名为TestB的Activity中。 2,隐式匹配(Implicit): 隐式匹配,首先要匹配Intent的几项值:Action, Category, Data/Type,Component.如果填写了Componet就是上例中的Test.class这就形成了显示匹配。所以此部分只讲前几种匹配。匹配规则为最大匹配规则, 1),如果你填写了Action,如果有一个程序的Manifest.xml中的某一个Activity的IntentFilter段中定义了包含了相同的Action那么这个Intent就与这个目标Action匹配,如果这个Filter段中没有定义Type,Category,那么这个Activity就匹配了。但是如果手机中有两个以上的程序匹配,那么就会弹出一个对话可框来提示说明。 Action的值在Android中有很多预定义,如果你想直接转到你自己定义的Intent接收者,你可以在接收者的IntentFilter中加入一个自定义的Action值(同时要设定Category值为"android.intent.category.DEFAULT"),在你的Intent中设定该值为Intent的Action,就直接能跳转到你自己的Intent接收者中。因为这个Action在系统中是唯一的。 2),data/type,你可以用Uri来做为data,比如 Uri uri = Uri.parse(http://www.google.com ); Intent i = new Intent(Intent.ACTION_VIEW,uri); 手机的Intent分发过程中,会根据http://www.google.com的scheme判断出数据类型type.手机的Brower则能匹配它,在Brower的Manifest.xml中的IntenFilter中首先有ACTION_VIEW Action,也能处理http:的type, 3),至于分类Category,一般不要去在Intent中设置它,如果你写Intent的接收者,就在Manifest.xml的Activity的IntentFilter中包含android.category.DEFAULT,这样所有不设置Category(Intent.addCategory(String c);)的Intent都会与这个Category匹配。 4),extras(附加信息),是其它所有附加信息的集合。使用extras可以为组件提供扩展信息,比如,如果要执行“发送电子邮件”这个动作,可以将电子邮件的标题、正文等保存在extras里,传给电子邮件发送组件。 11.如果后台的Activity由于某原因被系统回收了,如何在被系统回收之前保存当前状态? 当你的程序中某一个Activity A 在运行时中,主动或被动地运行另一个新的Activity B 这个时候A会执行 public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); outState.putLong("id", 1234567890); } B 完成以后又会来找A, 这个时候就有两种情况,一种是A被回收,一种是没有被回收,被回收的A就要重新调用onCreate()方法,不同于直接启动的是这回onCreate()里是带上参数savedInstanceState,没被收回的就还是onResume就好了。 savedInstanceState是一个Bundle对象,你基本上可以把他理解为系统帮你维护的一个Map对象。在onCreate()里你可能会 用到它,如果正常启动onCreate就不会有它,所以用的时候要判断一下是否为空。 if(savedInstanceState != null){ long id = savedInstanceState.getLong("id"); } 12.请解释下在单线程模型中Message、Handler、Message Queue、Looper之间的关系。 答:简单的说,Handler获取当前线程中的looper对象,looper用来从存放Message的MessageQueue中取出Message,再有Handler进行Message的分发和处理. Message Queue(消息队列):用来存放通过Handler发布的消息,通常附属于某一个创建它的线程,可以通过Looper.myQueue()得到当前线程的消息队列 Handler:可以发布或者处理一个消息或者操作一个Runnable,通过Handler发布消息,消息将只会发送到与它关联的消息队列,然也只能处理该消息队列中的消息 Looper:是Handler和消息队列之间通讯桥梁,程序组件首先通过Handler把消息传递给Looper,Looper把消息放入队列。Looper也把消息队列里的消息广播给所有的 Handler:Handler接受到消息后调用handleMessage进行处理 Message:消息的类型,在Handler类中的handleMessage方法中得到单个的消息进行处理 在单线程模型下,为了线程通信问题,Android设计了一个Message Queue(消息队列), 线程间可以通过该Message Queue并结合Handler和Looper组件进行信息交换。下面将对它们进行分别介绍: 1. Message Message消息,理解为线程间交流的信息,处理数据后台线程需要更新UI,则发送Message内含一些数据给UI线程。 2. Handler Handler处理者,是Message的主要处理者,负责Message的发送,Message内容的执行处理。后台线程就是通过传进来的 Handler对象引用来sendMessage(Message)。而使用Handler,需要implement 该类的 handleMessage(Message)方法,它是处理这些Message的操作内容,例如Update UI。通常需要子类化Handler来实现handleMessage方法。 3. Message Queue Message Queue消息队列,用来存放通过Handler发布的消息,按照先进先出执行。 每个message queue都会有一个对应的Handler。Handler会向messagequeue通过两种方法发送消息:sendMessage或post。这两种消息都会插在message queue队尾并按先进先出执行。但通过这两种方法发送的消息执行的方式略有不同:通过sendMessage发送的是一个message对象,会被 Handler的handleMessage()函数处理;而通过post方法发送的是一个runnable对象,则会自己执行。 4. Looper Looper是每条线程里的Message Queue的管家。Android没有Global的MessageQueue,而Android会自动替主线程(UI线程)建立Message Queue,但在子线程里并没有建立Message Queue。所以调用Looper.getMainLooper()得到的主线程的Looper不为NULL,但调用Looper.myLooper()得到当前线程的Looper就有可能为NULL。对于子线程使用Looper,API Doc提供了正确的使用方法:这个Message机制的大概流程: 1. 在Looper.loop()方法运行开始后,循环地按照接收顺序取出Message Queue里面的非NULL的Message。 2. 一开始Message Queue里面的Message都是NULL的。当Handler.sendMessage(Message)到Message Queue,该函数里面设置了那个Message对象的target属性是当前的Handler对象。随后Looper取出了那个Message,则调用 该Message的target指向的Hander的dispatchMessage函数对Message进行处理。在dispatchMessage方法里,如何处理Message则由用户指定,三个判断,优先级从高到低: 1) Message里面的Callback,一个实现了Runnable接口的对象,其中run函数做处理工作; 2) Handler里面的mCallback指向的一个实现了Callback接口的对象,由其handleMessage进行处理; 3) 处理消息Handler对象对应的类继承并实现了其中handleMessage函数,通过这个实现的handleMessage函数处理消息。 由此可见,我们实现的handleMessage方法是优先级最低的! 3. Handler处理完该Message (updateUI) 后,Looper则设置该Message为NULL,以便回收! 在网上有很多文章讲述主线程和其他子线程如何交互,传送信息,最终谁来执行处理信息之类的,个人理解是最简单的方法——判断Handler对象里面的Looper对象是属于哪条线程的,则由该线程来执行! 1. 当Handler对象的构造函数的参数为空,则为当前所在线程的Looper; 2. Looper.getMainLooper()得到的是主线程的Looper对象,Looper.myLooper()得到的是当前线程的Looper对象。 13.View, surfaceView, GLSurfaceView有什么区别 view是最基础的,必须在UI主线程内更新画面,速度较慢。 SurfaceView 是view的子类,类似使用双缓机制,在新的线程中更新画面所以刷新界面速度比view快 GLSurfaceView 是SurfaceView的子类,opengl 专用的 14.根据自己的理解描述下Android数字签名 (1)所有的应用程序都必须有数字证书,Android系统不会安装一个没有数字证书的应用程序 (2)Android程序包使用的数字证书可以是自签名的,不需要一个权威的数字证书机构签名认证 (3)如果要正式发布一个Android程序,必须使用一个合适的私钥生成的数字证书来给程序签名,而不能使用adt插件或者ant工具生成的调试证书来发布。 (4)数字证书都是有有效期的,Android只是在应用程序安装的时候才会检查证书的有效期。如果程序已经安装在系统中,即使证书过期也不会影响程序的正常功能。 15.Dalvik基于JVM的改进 1.几个class变为一个dex,constant pool,省内存 2.Zygote,copy-on-write shared,省内存,省cpu,省电 3.基于寄存器的bytecode,省指令,省cpu,省电 4.Trace-based JIT,省cpu,省电,省内存 16.android中有哪几种解析xml的类,官方推荐哪种?以及它们的原理和区别 Ø DOM解析 优点: 1.XML树在内存中完整存储,因此可以直接修改其数据和结构. 2.可以通过该解析器随时访问XML树中的任何一个节点. 3.DOM解析器的API在使用上也相对比较简单. 缺点: 如果XML文档体积比较大时,将文档读入内存是非常消耗系统资源的. 使用场景: DOM 是用与平台和语言无关的方式表示 XML 文档的官方 W3C 标准.DOM 是以层次结构组织的节点的集合.这个层次结构允许开发人员在树中寻找特定信息.分析该结构通常需要加载整个文档和构造层次结构,然后才能进行任何工作.DOM是基于对象层次结构的. Ø SAX解析 优点: SAX 对内存的要求比较低,因为它让开发人员自己来决定所要处理的标签.特别是当开发人员只需要处理文档中所包含的部分数据时,SAX 这种扩展能力得到了更好的体现. 缺点: 用SAX方式进行XML解析时,需要顺序执行,所以很难访问到同一文档中的不同数据.此外,在基于该方式的解析编码过程也相对复杂. 使用场景: 对于含有数据量十分巨大,而又不用对文档的所有数据进行遍历或者分析的时候,使用该方法十分有效.该方法不用将整个文档读入内存,而只需读取到程序所需的文档标签处即可. Ø Xmlpull解析 android SDK提供了xmlpull api,xmlpull和sax类似,是基于流(stream)操作文件,然后根据节点事件回调开发者编写的处理程序.因为是基于流的处理,因此xmlpull和sax都比较节约内存资源,不会象dom那样要把所有节点以对橡树的形式展现在内存中.xmlpull比sax更简明,而且不需要扫描完整个流. 17.双缓冲技术原理以及优缺点 创建一幅后台图像,将每一帧画入图像,然后调用drawImage()方法将整个后台图像一次画到屏幕上去。 优点:双缓冲技术的优点在于大部分绘制是离屏的。 将离屏图像一次绘至屏幕上,比直接在屏幕上绘制要有效得多。 双缓冲技术可以使动画平滑。 缺点:要分配一个后台图像的缓冲,如果图像相当大,这将占用很大一块内存。 18.Socket通信编程 客户端编程步骤: 1、 创建客户端套接字(指定服务器端IP地址与端口号) 2、 连接(Android 创建Socket时会自动连接) 3、 与服务器端进行通信 4、 关闭套接字 服务器端: 1.创建一个ServerSocket,用于监听客户端Socket的连接请求 2.采用循环不断接受来自客户端的请求 3.每当接受到客户端Socket的请求,服务器端也对应产生一个Socket 本文转自我爱物联网博客园博客,原文链接:http://www.cnblogs.com/yydcdut/p/3907466.html,如需转载请自行联系原作者

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。