Adroid studio常用技巧
Android studio 是Google官方定制的Android开发工具,俗话说工欲善其事必先利其器,充分利用开发工具不仅能大大提高工作效率,同时也是个人能力的一种体现。在此提供关键字和官方文档方便查阅和记忆
Android studio 是Google官方定制的Android开发工具,俗话说工欲善其事必先利其器,充分利用开发工具不仅能大大提高工作效率,同时也是个人能力的一种体现。在此提供关键字和官方文档方便查阅和记忆
题目链接:Pascal’s Triangle
Given numRows, generate the first numRows of Pascal’s triangle.
For example, given numRows = 5,
Return
1 | [ |
这道题比较简单,属于基础的数组操作。知道规律就好做了,它的规律如下:
1.每行的元素个数等于行数
2.每行的第一个元素和最后一个元素等于1
3.第三行起,每行除第一个和最后一个元素外之间的元素第i行第k个元素 = 行数i-1行第k个元素 + 行数i-1行第k-1元素
4.隐藏条件:当行数i和元素j的下表相等时 ,i行的第j个元素等于1
具体代码如下:
1 | //方法一 |
算法时间复杂度应该是O(1+2+3+…+n)=n(n-1)/2=O(n^2),空间上只需要二维数组来存储结果,不需要额外空间。
题目链接 Plus One
Given a non-negative number represented as an array of digits, plus one to the number.
The digits are stored such that the most significant digit is at the head of the list.
这道题很简单,就是考加法的进位运算问题对一个数组进行加一操作,具体思路:
维护一个进位,对每一位进行加一,然后判断进位,如果有继续到下一位,否则就可以返回了,因为前面不需要计算了。有一个小细节就是如果到了最高位进位仍然存在,那么我们必须重新new一个数组,然后把第一个为赋成1(因为只是加一操作,其余位一定是0,否则不会进最高位)。代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15public static int[] plusOne(int[] digit){
int one = 1;
int sum = 0;
for(int i = digit.length -1 ; i >= 0; i--){
sum = digit[i] + one;
digit[i] = sum % 10; //取余
one = sum / 10; //取整
if(one == 0){ //无需进位,则返回即可
return digit;
}
}
int[] res = new int[digit.length + 1]; //当最高位仍需进位则重新new一个数组
res[0] = 1;
return res;
}
因为只需要一次扫描,所以算法复杂度是O(n),n是数组的长度。而空间上,一般情况是O(1),但是如果数是全9,那么是最坏情况,需要O(n)的额外空间。
创建自己的项目
了解过去自身的思考行为方式
准备好问面试官的问题
*关注基础算法和数据结构,非“有意思”的题目
*
1 | $ git branch --set-upstream-to=origin/dev2.2 master |
远程分支在前,本地分支在后。
关联之后就可以正常的pull代码了。
1 | $ git branch -a |
1 | $ git branch -vv |
根据这张图片可以看出
Git merge –no-ff 可以保存你之前的分支历史。能够更好的查看 merge历史,以及branch 状态。
git merge 则不会显示 feature,只保留单条分支记录。
1.Git merge 会生成一个新得合并节点,而rebase不会
比如:
1 | D---E test |
使用merge合并, 为分支合并自动识别出最佳的同源合并点: git merge master
1 | D--------E |
操作会舍弃 master 分支上提取的 commit,同时不会像 merge 一样生成一个合并修改内容的 commit,相当于把 master 分支(当前所在分支)上的修改在 deve 分支(目标分支)上原样复制了一遍:git rebase test
1 | A---B---D---E---C'---F' test, master |
使用git pull时默认是merge, 加 –rebase参数使其使用rebase方式
1 | git pull --rebase |
2.rebase和merge的不同适用场景
rebase场景:如果修改了某个公用代码的BUG,这个时候就应该是把所有的OEM版本分支rebase到这个修复BUG的分支上来,在rebase过程中,Git会要你手动解决代码上的冲突,你需要做的就是把修复BUG的代码放到目标分支代码里面去。rebase的结果是:所有的分支依然存在
merge场景:因为成员的代码开发工作已经完成了,也不需要再保留这个分支了,所以我们可以把这个成员分支merge到主分支上,当然冲突在所难免,手工解决的工作肯定逃不掉,但是利大于弊不是吗。merge以后,分支就不存在了,但是在git的所有分支历史中还能看到身影。
一般我们把别的分支合并到master时用merge,而把master合并到别的分支时会用到rebase的原因,这是因为master分支一般commit会比较频繁。
所以每次下拉代码fetch之后用rebase的原因就是:
本地commit之后,fetch远端代码,此时,远端代码可能会被若干人修改会有若干个commit,而本地就一个commit,然后git rebase的时候,是默认rebase 远端代码,此时会将本地commit应用到远端代码,也就只需要解决一次冲突,并且rebase之后没有新的commit,很友好。但是,如果使用merge,则会产生新的commit。
比如dev是你的公共开发分支*
git checkout dev # 本地切到公共分支
git pull # 将本地的dev更新
git checkout -b bug_101026 # 新建一个主题分支(一个bug,一个功能什么的)
… # 改动.. commit.. 测试…
git fetch origin # 更新upstream
git rebase origin/dev # 将你的commits移到的末尾
git checkout dev # 切换到公共分支
git pull # 更新公共分支
git rebase bug_101026 # 将你的主题分支加到公共分支的末尾
git push # 推送
基本数据类型与引用数据类型
8种基本数据类型
引用数据类型:类、接口类型、数组类型、枚举类型、注解类型。
区别:
基本数据类型在被创建时,在栈上给其划分一块内存,将数值直接存储在栈上。
引用数据类型在被创建时,首先要在栈上给其引用(句柄)分配一块内存,而对象的具体信息都存储在堆内存上,然后由栈上面的引用指向堆中对象的地址。
例如,有一个类Person,有属性name,age,带有参的构造方法,
Person p = new Person(“zhangsan”,20);
在内存中的具体创建过程是:
1.首先在栈内存中位其p分配一块空间;
2.在堆内存中为Person对象分配一块空间,并为其三个属性设初值””,0;
3.根据类Person中对属性的定义,为该对象的两个属性进行赋值操作;
4.调用构造方法,为两个属性赋值为”Tom”,20;(注意这个时候p与Person对象之间还没有建立联系);
5.将Person对象在堆内存中的地址,赋值给栈中的p;通过引用(句柄)p可以找到堆中对象的具体信息。
静态区: 保存自动全局变量和 static 变量(包括 static 全局和局部变量)。静态区的内容在整个程序的生命周期内都存在,由编译器在编译的时候分配。
堆区: 一般由程序员分配释放,由 malloc 系列函数或 new 操作符分配的内存,其生命周期由 free 或 delete 决定。在没有释放之前一直存在,直到程序结束,由OS释放。其特点是使用灵活,空间比较大,但容易出错
栈区: 由编译器自动分配释放,保存局部变量,栈上的内容只在函数的范围内存在,当函数运行结束,这些内容也会自动被销毁,其特点是效率高,但空间大小有限
文字常量区: 常量字符串就是放在这里的。 程序结束后由系统释放。
程序代码区:存放函数体的二进制代码。

在Java中,所有的对象变量都是引用,Java通过引用来管理对象。然而在给方法传参时,Java并没有使用传引用的方式,而是采用了传值的方式。
例如下面的badSwap()方法:
1 | public void badSwap(int var1, int var2) |
当badSwap方法结束时,原有的var1和var2的值并不会发生变化。即使我们用其它Object类型来替代int,也不会有变化,因为Java在传递引用时也是采用传值的方式。(译者注:这里是关键,全文的核心是:1. Java中对象变量是引用 2. Java中方法是传值的 3. 传方法中参数时,传递的是引用的值)
代码:
1 | public void tricky(Point arg1, Point arg2) |
执行main()的输出如下:
1 | X: 0 Y: 0 |
这个方法成功地改变了pnt1的值,但pnt1和pnt2的交换却失败了!这是Java参数传递机制里最让人迷惑的地方。在main()中,pnt1和pnt2是Point对象的引用,当将pnt1和pnt2传递给tricky()时,Java使用的正是传值的方式,将这两个引用的传给了arg1和arg2。也就是说arg1和arg2正是pnt1和pnt2的复制,他们所指向的对象是相同的。详情可见下面的图示:
1 | try{} catch(){}finally{} return; |
1 | try{ return; }catch(){} finally{} return; |
1 | try{ } catch(){return;} finally{} return; |
1 | try{ return; }catch(){} finally{return;} |
1 | try{} catch(){return;}finally{return;} |
1 | try{ return;}catch(){return;} finally{return;} |
这里涉及到java的引用传递和值传递,首先要明白java全部都是传值的。对于基本数据类型的值是存在栈中的,它是将数据完完整整的拷贝,生成一个新的变量值;对于引用类型的数据既对象它的数据存在于堆中,栈中保存的是指向数据的引用地址,它是将对象的引用地址值拷贝了,所以修改了对象内容,但地址值是不变的。
测试代码code1
1 | public class FinallyTest { |
输出2
测试代码code2
1 |
|
测试输出结果:
zs
ls
ww
mz
wq
yyy
所以可得
如果finally中没有return语句,但是改变了要返回的值,这里有点类似与引用传递和值传递的区别,分以下两种情况:
1)如果return的数据是基本数据类型或文本字符串,则在finally中对该基本数据的改变不起作用,try中的return语句依然会返回进入finally块之前保留的值。
2)如果return的数据是引用数据类型,而在finally中对该引用数据类型的属性值的改变起作用,try中的return语句返回的就是在finally中改变后的该属性的值。
最终结论:
任何执行try或者catch中的return语句之前,都会先执行finally语句,如果finally存在的话。如果finally中有return语句,那么程序就return了,所以finally中的return是一定会被return的,编译器把finally中的return实现为一个warning。