//今天京东通知面试了,一面面完,我以为我玩完了。。唉。。。不过记录一下本身的面试经验仍是很重要的(虽然只是一个实习面试),为下次的面试作准备吧。html
先是问了一下总成绩,数据结构,算法的成绩,而后问了以前有没有作过相关的安卓工程,问了简历上的实习经历和项目经历。由于本身面的是安卓开发,因此重点问的是安卓的项目和获奖项目。前端
以后是一些专业性的问题:java
1.字母组合的代码:abc三个字母组合能够组合成6种,abc,acb,bac,bca,cab,cba,而aac的组合只有3种,aac,caa,aca,输出用户输入字符串的全部排列组合结果。(算法题)面试
2.JAVA的面向对象编程三大特征:封装,继承,多态,解释这三个概念并用代码解释;java的继承题目,A extends B,new A(),输出结果算法
3.死锁的定义,用代码写死锁;编程
4.onNewInent数据结构
5.安卓开发时,前端和后台传递数据的方法;多线程
解:1.参考全排列ide
2.内容来源:Java面向对象的三大特征post
封装和继承几乎都是为多态而准备的
1)修改属性的可见性来限制对属性的访问
2)为每一个属性建立一队赋值和取值方法,用于对这些属性的访问
3)在赋值和取值方法中,加入对属性的存取限制
为了实现良好的封装,咱们一般将类的成员变量声明为private,在经过public方法来对这个变量来访问。对一个变量的操做,通常有读取和赋值2个操做,,咱们分别定义2个方法来实现这2个操做,一个是getXX(XX表示要访问的成员变量的名字)用来读取这个成员变量,另外一个是setXX()用来对这个变量赋值。
例子:
public class Husband { /* * 对属性的封装一我的的姓名、性别、年龄、妻子都是这我的的私有属性 */ private String name; private String sex; private int age; private Wife wife; /* * setter()、getter()是该对象对外开发的接口 */ public String getName() { return name; } public void setName(String name) { this.name = name; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public void setWife(Wife wife) { this.wife = wife; } }
继承所表达的就是一种对象类之间的相交关系,它使得某类对象能够继承另一类对象的数据成员和成员方法。若类B继承类A,则属于B的对象便具备类A的所有或部分性质(数据属性)和功能(操做),咱们称被继承的类A为基类、父类或超类,而称继承类B为A的派生类或子类。
继承避免了对通常类和特殊类之间共同特征进行的重复描述。同时,经过继承能够清晰地表达每一项共同特征所适应的概念范围——在通常类中定义的属性和操做适应于这个类自己以及它如下的每一层特殊类的所有对象。运用继承原则使得系统模型比较简练也比较清晰。
继承的实例
class Person1 { public String name = "xiaomiao"; public int age = 20; } class Student extends Person1 { void study() { System.out.println("I can study!"); } } public class JiCheng { public static void main(String args[]) { Student stu = new Student(); // stu.name = "zhangsan"; // stu.age = 20; System.out.println("name=" + stu.name + ",,," + "age=" + stu.age); } }
方法的重写、重载与动态链接构成多态性;
Java之因此引入多态的概念,缘由之一是它在类的继承问题上和C++不一样,后者容许多继承,这确实给其带来的很是强大的功能,可是复杂的继承关系也给C++开发者带来了更大的麻烦,为了规避风险,Java只容许单继承,派生类与基类间有IS-A的关系(即“猫”is a “动物”)。这样作虽然保证了继承关系的简单明了,可是势必在功能上有很大的限制,因此,Java引入了多态性的概念以弥补这点的不足,此外,抽象类和接口也是解决单继承规定限制的重要手段。同时,多态也是面向对象编程的精髓所在。
要理解多态性,首先要知道什么是“向上转型”。
我定义了一个子类Cat,它继承了Animal类,那么后者就是前者的父类。我能够经过
Cat c = new Cat(); 例化一个Cat的对象,这个不难理解。
但当我这样定义时: Animal a = new Cat();
这表明什么意思呢?
很简单,它表示我定义了一个Animal类型的引用,指向新建的Cat类型的对象。因为Cat是继承自它的父类Animal,因此Animal类型的引用是能够指向Cat类型的对象的。那么这样作有什么意义呢?由于子类是对父类的一个改进和扩充,因此通常子类在功能上较父类更强大,属性较父类更独特,定义一个父类类型的引用指向一个子类的对象既可使用子类强大的功能,又能够抽取父类的共性。因此, 父类引用只能调用父类中存在的方法和属性,不能调用子类的扩展部分;由于父类引用指向的是堆中子类对象继承的父类;(可是若是强制把超类转换成子类的话,就能够调用子类中新添加而超类没有的方法了。)
同时,父类中的一个方法只有在父类中定义而在子类中没有重写的状况下,才能够被父类类型的引用调用;
对于父类中定义的方法,若是子类中重写了该方法,那么父类类型的引用将会调用子类中的这个方法,这就是动态链接。
3.内容来源:多线程死锁的产生以及如何避免死锁
死锁是指多个线程因竞争资源而形成的一种僵局(互相等待),若无外力做用,这些进程都将没法向前推动。
产生死锁必须同时知足如下四个条件,只要其中任一条件不成立,死锁就不会发生。
/** * 一个简单的死锁类 * 当DeadLock类的对象flag==1时(td1),先锁定o1,睡眠500毫秒 * 而td1在睡眠的时候另外一个flag==0的对象(td2)线程启动,先锁定o2,睡眠500毫秒 * td1睡眠结束后须要锁定o2才能继续执行,而此时o2已被td2锁定; * td2睡眠结束后须要锁定o1才能继续执行,而此时o1已被td1锁定; * td一、td2相互等待,都须要获得对方锁定的资源才能继续执行,从而死锁。 */ public class DeadLock implements Runnable { public int flag = 1; //静态对象是类的全部对象共享的 private static Object o1 = new Object(), o2 = new Object(); @Override public void run() { System.out.println("flag=" + flag); if (flag == 1) { synchronized (o1) { try { Thread.sleep(500); } catch (Exception e) { e.printStackTrace(); } synchronized (o2) { System.out.println("1"); } } } if (flag == 0) { synchronized (o2) { try { Thread.sleep(500); } catch (Exception e) { e.printStackTrace(); } synchronized (o1) { System.out.println("0"); } } } } public static void main(String[] args) { DeadLock td1 = new DeadLock(); DeadLock td2 = new DeadLock(); td1.flag = 1; td2.flag = 0; //td1,td2都处于可执行状态,但JVM线程调度先执行哪一个线程是不肯定的。 //td2的run()可能在td1的run()以前运行 new Thread(td1).start(); new Thread(td2).start(); } }
4.内容来源:Activity生命周期与onNewIntent
Activity第一次启动时:onCreate -> onStart -> onResume
Activity再次启动时:onPause(原来的实例) -> onCreate(新的实例) -> onStart(新的实例) -> onResume(新的实例) -> onStop(原来的实例)
因此,标准模式下,activity被屡次启动,不会回调onNewIntent方法。
Activity第一次启动时:onCreate -> onStart -> onResume
Activity再次启动时:onPause -> onNewInent -> onResume
Activity第三次启动时:onPause -> onNewInent -> onResume
因此,非标准模式下,activity第一次被启动,会正常回调生命周期方法,不会回调onNewIntent方法。屡次启动该activity后,均会调用 onNewInent方法。
注意:当调用到onNewIntent(intent)时,该参数的intent是最新的intent,可在onNewIntent中使用setIntent(intent),这样后续使用getIntent()时将得到最新的intent.不然,后续getIntent()获得的是旧的intent。
A画面singleTask模式下:
画面以下跳转:
A-B-A
A的生命周期以下,开发者模式中,保留活动:
1. A启动:onCreate: null == savedInstanceState -> onStart -> onResume
2. 跳转到B:onStop
3. 跳转到A:onNewIntent -> onRestart -> onStart -> onResume
A的生命周期以下,开发者模式中,不保留活动:
1. A启动:onCreate: null == savedInstanceState -> onStart -> onResume
2. 跳转到B:onStop -> onDestroy
3. 跳转到A:onCreate: null == savedInstanceState -> onStart -> onResume
也就是说,不会走onNewIntent
主画面设置成singleTask模式,那么在退出登陆后,从新statActivity主画面,而且intent传入一个标志位:
1.主画面未被异常关闭时,此时会走onNewIntent()方法,而且主画面之上的画面会被推出栈,在该方法中根据intent传入的标志位,启动从新登陆画面,关闭主画面;
2.主画面被异常关闭时,此时不会走onNewIntent()方法,而且主画面之上的画面会被推出栈,在onCreate方法中根据intent传入的标志位,启动从新登陆画面,关闭主画面。
注意:
activity异常退出的时候,好比屏幕横竖切换、内存不足低优先级的activity被杀死,ondestroy仍然会被调用,除非直接退出整个进程System.exit(0)不会调用ondestroy。