尾声
以薪资待遇为基础,以发展为最终目标,要在高薪资的地方,谋求最好的发展!
下面是有几位Android行业大佬对应上方技术点整理的一些进阶资料。
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
final finalList1 = [1, 2];
final finalList2 = [1, 2];
print(identical(finalList1, finalList2)); //identical用于检查两个引用是否指向同一个对象
const constList1 = [1, 2];
const constList2 = [1, 2];
print(identical(constList1, constList2));
上面代码的运行结果是false和ture,也印证了上面所说的。
- const需要是编译时常量
final DateTime finalDateTime = DateTime.now();
// const DateTime constDateTime = DateTime.now();//DateTime.now() 是运行期计算出来的值
小总结
本小节简单说明了在Dart中变量的一些细节问题,如有补充或者错误可直接在评论区说出来,不要给我面子😂。
内置类型
概述
在Dart中,内置类型有以下几种:Numbers 数值、Strings 字符串、Booleans 布尔值、Lists 列表(数组)、Sets 集合、Maps 集合、Runes 符号字符、Symbols 标识符。
num, int, double
int和double大家都很熟悉,int还是整数值,double是64-bit双精度浮点数。这里需要着重看一下num,int和double是num的子类。剩下的就没什么好说的了,其他的使用方法和Java基本一样,只是可以直接定义num类型的数据,剩下的大家直接看下面的代码应该就明白了:
int i = 1; //整数值
double d = 1.0; //double 64-bit (双精度) 浮点数
int bitLength = i.bitLength;
print(‘bitLength: ${bitLength}’); //bitLength判断int值需要多少bit位
double maxFinite = double.maxFinite;
print(‘maxFinite: ${maxFinite}’); //maxFinitedouble的最大值
//int和double都是num的子类
num n1 = 1;
num n2 = 1.0;
//支持十进制、十六进制
int i1 = 0xfff;
//科学计数法
double d1 = 1.2e2; //120.0
//转换
//String->int
int i2 = int.parse(‘1’);
double d2 = 1; //当double的值为int值时,int自动转成double
print(‘d2: ${d2}’);
// int i2 = int.tryParse(‘1.0’);//返回null
String
- Dart 字符串是 UTF-16 编码的字符序列,可以使用单引号或者双引号来创建字符串
main(){
String a = ‘zhujiang’;
String b = “zhujiang”;
}
- 可以使用三个单引号或者双引号创建多行字符串对象
String c = “dd”
“sssdffg”
“vftgt”;
String d = ‘’‘ssss
fffffffgg
grrrr’‘’;
- 可以使用 r 前缀创建”原始raw”字符串。
String e = ‘’‘ssss
fff\nffffgg
grrrr’‘’;
String f = r’‘‘ssss
fff\nffffgg
grrrr’’';
print(e);
print(f);
这里需要说明一下,如果使用r前缀,即是原始字符串,\n换行会直接打印出来而不会实现换行,下面是执行结果:
lib/2-type.dart: Warning: Interpreting this as package URI, ‘package:darttest/2-type.dart’.
ssss
fff
ffffgg
grrrr
ssss
fff\nffffgg
grrrr
- 可以在字符串中使用表达式: ${expression},如果表达式是一个标识符,可以省略 {},如果表达式的结果为一个对象,则 Dart 会调用对象的 toString() 函数来获取一个字符串。
print(“object:$c”);
这里既然已经说到String了,那就再说一下StringBuffer吧,使用方法和Java一样,但是可以省略new关键字,还可以进行链式调用:
StringBuffer stringBuffer = StringBuffer();
stringBuffer…write(“sss”)…write(“ssss”);
bool
这里的bool相当于Java中boolean,这里只需要记着bool对象未初始化的默认值是null(上一篇文章中提到过)
List
- Dart中可以直接打印list包括list的元素,List也是对象(java中直接打印list结果是地址值)。
print(List)
这里会直接输出List。
-
Dart中List的下标索引和java一样从0开始
-
和java一样支持泛型。
-
有增删改查,支持倒序,自带排序、洗牌,可使用+将两个List合并
//常用方法 增删改查,排序,洗牌,复制子列表
var list4 = [];
//增
list4.add(1);
print(‘add 1 :
l
i
s
t
4
′
)
;
/
/
删
l
i
s
t
4.
r
e
m
o
v
e
(
5
)
;
p
r
i
n
t
(
′
r
e
m
o
v
e
5
:
{list4}'); //删 list4.remove(5); print('remove 5 :
list4′);//删list4.remove(5);print(′remove5:{list4}’);
list4.removeAt(2);
print(‘remove at 0 :
l
i
s
t
4
′
)
;
/
/
改
l
i
s
t
4
[
4
]
=
5
;
p
r
i
n
t
(
′
u
p
d
a
t
e
l
i
s
t
4
[
4
]
t
o
5
:
{list4}'); //改 list4[4] = 5; print('update list4[4] to 5 :
list4′);//改list4[4]=5;print(′updatelist4[4]to5:list4}’);
//range
list4.fillRange(0, 3, 9);
print(‘fillRange update list4[0]-list4[2] to 9 :KaTeX parse error: Expected 'EOF', got '}' at position 6: list4}̲'); Iterable ge…getRange}’);
//查
var contains = list4.contains(5);
print(‘list4 contains 5 :
c
o
n
t
a
i
n
s
′
)
;
v
a
r
i
n
d
e
x
O
f
=
l
i
s
t
4.
i
n
d
e
x
O
f
(
1
)
;
p
r
i
n
t
(
′
l
i
s
t
4
i
n
d
e
x
O
f
1
:
{contains}'); var indexOf = list4.indexOf(1); print('list4 indexOf 1 :
contains′);varindexOf=list4.indexOf(1);print(′list4indexOf1:{indexOf}’);
int indexWhere = list4.indexWhere((test) => test == 5);
print(‘list4 indexWhere 5 :
i
n
d
e
x
W
h
e
r
e
′
)
;
/
/
排序
l
i
s
t
4.
s
o
r
t
(
)
;
p
r
i
n
t
(
′
l
i
s
t
4
s
o
r
t
:
{indexWhere}'); //排序 list4.sort(); print('list4 sort :
indexWhere′);//排序list4.sort();print(′list4sort:{list4}’);
//洗牌
list4.shuffle();
print(‘list4 shuffle :
l
i
s
t
4
′
)
;
/
/
复制子列表
v
a
r
l
i
s
t
5
=
l
i
s
t
4.
s
u
b
l
i
s
t
(
1
)
;
p
r
i
n
t
(
′
s
u
b
l
i
s
t
(
1
)
l
i
s
t
5
:
{list4}'); //复制子列表 var list5 = list4.sublist(1); print('sublist(1) list5 :
list4′);//复制子列表varlist5=list4.sublist(1);print(′sublist(1)list5:{list5}’);
//操作符
var list6 = [8, 9];
print(‘list6 :
l
i
s
t
6
′
)
;
v
a
r
l
i
s
t
7
=
l
i
s
t
5
+
l
i
s
t
6
;
p
r
i
n
t
(
′
l
i
s
t
5
+
l
i
s
t
6
:
{list6}'); var list7 = list5 + list6; print('list5 + list6 :
list6′);varlist7=list5+list6;print(′list5+list6:{list7}’);
这里的代码比较长,但是很好理解,就是一个集合的增删改查和一些比较常用的方法,大家可以自己手写一下加深理解。
Map
map这里就不多说了,和Java类似
Set
Set这里其实也和Java差不多,但是有几个地方需要说明一下:
- set1.difference(set2):返回set1集合里有但set2里没有的元素集合
- set1.intersection(set2):返回set1和set2的交集
- set1.union(set2):返回set1和set2的并集
- set1.retainAll():set1只保留某些元素(要保留的元素要在原set中存在)
这几个方法非常好用,简单写一下伪代码大家看一下吧:
var difference12 = set1.difference(set2);
var difference21 = set2.difference(set1);
print(‘set1 difference set2 :
d
i
f
f
e
r
e
n
c
e
12
′
)
;
/
/
返回
s
e
t
1
集合里有但
s
e
t
2
里没有的元素集合
p
r
i
n
t
(
′
s
e
t
2
d
i
f
f
e
r
e
n
c
e
s
e
t
1
:
{difference12}'); //返回set1集合里有但set2里没有的元素集合 print('set2 difference set1 :
difference12′);//返回set1集合里有但set2里没有的元素集合print(′set2differenceset1:{difference21}’); //返回set2集合里有但set1里没有的元素集合
var intersection = set1.intersection(set2);
print(‘set1 set2交集 :
i
n
t
e
r
s
e
c
t
i
o
n
′
)
;
/
/
返回
s
e
t
1
和
s
e
t
2
的交集
v
a
r
u
n
i
o
n
=
s
e
t
1.
u
n
i
o
n
(
s
e
t
2
)
;
p
r
i
n
t
(
′
s
e
t
1
s
e
t
2
并集
:
{intersection}'); //返回set1和set2的交集 var union = set1.union(set2); print('set1 set2并集 :
intersection′);//返回set1和set2的交集varunion=set1.union(set2);print(′set1set2并集:{union}’); //返回set1和set2的并集
set2.retainAll([‘aa’, ‘flutter’]); //只保留(要保留的元素要在原set中存在)
print(‘set2只保留aa flutter 😒{set2}’);
Runes
表示符文的意思,用于在字符串中表示Unicode字符。使用String.fromCharCodes显示字符图形。如果非4个数值,需要把编码值放到大括号中。
Runes runes = new Runes('\u{1f605} \u6211‘);
var str1 = String.fromCharCodes(runes);
print(str1);
直接这样写就可以了,下面看一下打印效果:
😅 我
直接可以打印出表情,有表情需求的可以直接使用Runes。
Symbol
Symbol标识符,以前主要是反射使用,但是现在mirrors模块已经被移除,所以没啥大用了,大家只要知道有这么一个内置类型就可以了。
方法
方法这一块很重要,写代码离不开方法啊,继续开车,抓稳了!
定义
- 可在函数内定义
void main(){
void test(){
}
}
和Java不同,Dart中的函数可以定义在函数内部(和Java的匿名内部类别搞混了)
- 定义函数时可省略类型(不建议)
main(){
test(){
// return null;
}
}
上面的函数可以写成下面这样,Dart中函数是Function类型的对象。所有的函数都返回一个值。如果没有指定返回值,则 默认把语句 return null; 作为函数的最后一个语句执行。
- 支持缩写语法 => (Kotlin是用=来实现)
main(){
print(test1());
}
test()=> “zhujiang”;
String test1(){
return “zhujiang”;
}
上面代码中的test()和test1()效果是一样的,“=>”相当于大括号和return
可选参数
既然是函数,那么肯定要传参,我在经过Java构造方法的摧残之后,看这个功能的时候泪流满面😭。为什么会这样呢?下面先来看一个咱们的Java类的构造函数:
public class Test {
private String name;
private int age;
private String address;
public Test(String name, int age, String address) {
this.name = name;
this.age = age;
this.address = address;
}
public Test(String name, String address) {
this.name = name;
this.address = address;
}
public Test(String name, int age) {
this.name = name;
this.age = age;
}
public Test(String name) {
this.name = name;
}
}
一个非常简单的构造方法,只是想要传参数形式多一点,竟然需要写这么多重载方法。。。那么下面咱们来看一下拿Dart写的同样功能的代码:
class Test{
String name;
int age;
String address;
Test(this.name, {this.age, this.address});
}
What?竟然可以这样?是的,可以这样。下面来详细说一下函数的可选参数。
可选命名参数
其实上面构造方法我使用的就是可选命名参数,写的时候其实很简单,只需要加上大括号就行。下面是使用方法:
main() {
print(add(a: 1, b: 3));
}
int add({int a = 1, int b}) {
return a + b;
}
上面的add方法调用的时候可以不填参数,也可以填任何一个参数,也可以将参数都填上。这里要注意:
- 如果a不填的话,默认值就是1,如果b不填,默认值就是null。
- 传参数的时候一定要记得写a:,不然会报错。
可选位置参数
和上面的可选命名参数不同,上面的函数如果想调用,必须命名再加上冒号才能使用,可选位置参数就不需要了。这里和上面一样,默认值可加可不加:
int add2(int a,[int b = 2,int c = 3]) {
return a + b;
}
下面是上面add2()方法的几种调用方式:
print(add2(1));
print(add2(1,2));
print(add2(1,1,3));
注意
上面的可选命名参数和可选位置参数,可使用list或map作为默认值,但必须是const。
int add3({List a = const [1,2,3], int b = 2}) {
return b;
}
匿名函数
可赋值给变量,通过变量调用。可在其他函数中直接调用或传递给其他函数。匿名函数分为无参匿名函数和有参匿名函数:
- 无参匿名函数
var printFun = () => print(“无参匿名函数”);
- 有参匿名函数
var printFun2 = (name) => print(“有参匿名函数 $name”);
printFun2(“sss”);
这里还有一个小的知识点:可以通过()调用,不推荐。
(() =>print(“***可以通过()调用,不推”))();
闭包
这里感觉没什么好说的,大家直接看代码应该就可以理解:
Function makeAddFunc(int x) {
x++;
return (int y) => x + y;
}
var makeAddFun = makeAddFunc(11);
print(makeAddFun(10));
就是创建一个方法,返回的也是一个方法,可以再继续调用。
函数别名
用typedef给函数起一个别名,使用比较方便。例如定义一个方法的回调,直接使用别名定义。没返回值,则只要参数匹配就行了,如果定义了返回值,则返回值不一样会报错。
typedef Fun1(int a, int b);
typedef Fun2<T, K>(T a, K b);
int add(int a, int b) {
print(‘a + b’);
return a + b;
}
class Demo1 {
Demo1(int f(int a, int b), int x, int y) {
var sum = f(x, y);
print(“sum1 = $sum”);
}
}
class Demo2 {
Demo2(Fun1 f, int x, int y) {
var sum = f(x, y);
print(“sum2 = $sum”);
}
}
class Demo3 {
Demo3(Fun2<int, int> f, int x, int y) {
var sum = f(x, y);
print(“sum3 = $sum”);
}
}
上面代码就是定义函数别名的方法,下面是调用方法:
Fun1 fun1 = add(11, 12);
操作符、流程控制语句、异常
这一小节看着东西应该挺多,其实很简单,好多都和Java基本一致。
操作符
上面这幅图中就是Dart中的操作符,标为黑色的操作符和Java中使用基本一样,这里也就不过多赘述,咱们来仔细看看标红Java中没有的操作符:
- 后缀操作: ?.
如果写过Kotlin的话,可以跳过这段了,这里的问号点和Kotlin中基本一致,都是为了判空而出现的,那么下面来看一下使用方式吧:
main() {
String a;
print(a.length != null ? a.length : ‘’);
}
上面就是咱们平时写的代码,一个三目表达式来进行判空。但是在Dart中可以不这样写,可以直接使用问号点。
main() {
String a;
//print(a.length != null ? a.length : '');
print(a?.length);
}
是不是很方便?以后判空可以直接使用**“?.”**了
- 除(取整):~/
这个操作符其实很简单,只是对数字进行取整,下面是实例代码:
print(1/2);
print(1~/2);
上面代码的输出值是0.5和0
- 类型操作:as
这个和Kotlin中的as也基本一样,是对数据进行类型转换,很简单,直接看代码:
num n = 1;
int n2 = n as int;
- 类型操作: is
num n1 = 1.0;
if(n1 is int){
print(“int”);
}else{
print(“double”);
}
- 类型操作:is!
从名称上就可以知道和上面的is正好相反,就不写代码验证了。
- 判空:??
这个上面也写出来了,意思就是判空,下面直接看一下使用方法吧:
bool aaa;
aaa = aaa ?? false;
- 级联:…
这个其实就是链式调用,之前的文章中写过,当时的例子是StringBuffer:
StringBuffer stringBuffer = StringBuffer();
stringBuffer…write(“sss”)…write(“ssss”);
操作符就说到这里吧,掌握好操作符在写代码的时候会事半功倍的,希望大家都能掌握好。
流程控制语句
这个,怎么说,稍微提一下吧,这个是基础的基础,Dart中的流程控制语句和Java基本一样,直接进行使用就行。
不是不想写,if语句、for循环、while循环、brake、continue、switch、case,没了,这就是Dart的流程控制语句,如出一辙。跳过。
异常
Dart 提供了 Exception 和 Error 类型, 以及一些子类型。还可以定义自己的异常类型。但是,Dart 代码可以抛出任何非 null 对象为异常,不仅仅是实现了 Exception 或者 Error 的对象。
下面这幅图是Dart中的Exception :
下面这幅图是Dart中的Error:
抛出异常
- 这个和Java中写法一样,所有的 Dart 异常是非检查异常。 方法不一定声明了他们所抛出的异常, 并且你不要求捕获任何异常。
// 抛出Exception 对象
// throw new FormatException(‘格式异常’);
// 抛出Error 对象
// throw new OutOfMemoryError();
- Dart 代码可以抛出任何非 null 对象为异常,不仅仅是实现了 Exception 或者 Error 的对象。
// 抛出任意非null对象
// throw ‘这是一个异常’;
捕获异常
- 所有的 Dart 异常是非检查异常。 方法不一定声明了他们所抛出的异常, 并且你不要求捕获任何异常。可以使用on 或者 catch 来声明捕获语句,也可以 同时使用。使用 on 来指定异常类型,使用 catch 来 捕获异常对象。
try {
throw new OutOfMemoryError();
} on OutOfMemoryError {
print(‘没有内存了’);
}
- catch() 可以带有一个或者两个参数, 第一个参数为抛出的异常对象, 第二个为堆栈信息 (一个 StackTrace 对象)。
try {
throw new OutOfMemoryError();
} catch (e, s) {
print(‘Exception details: $e’);
print(‘Stack Trace: $s’);
} finally {
print(‘end’);
}
- 可以使用rethrow把捕获的异常重新抛出。
try {
throw new OutOfMemoryError();
} catch (e, s) {
print(‘Exception details: $e’);
print(‘Stack Trace: $s’);
rethrow;
}
类的点点滴滴
前几小节分别讲解了Dart中的变量、内置类型、函数(方法)、操作符、流程控制语句和异常,对Dart的基本语法已经有了很多的了解,那么接来说一下Dart中的类。
构造函数
前几篇文章中在讲函数(方法)的一篇中提到过,这里再说一下吧,首先来看一下Java中构造函数的写法:
class Point {
double x;
double y;
Point(int x, int y) {
this.x = x;
this.y = y;
}
}
下面是dart中的建议写法:
class Point {
num x;
num y;
Point(this.x, this.y);
}
命名构造函数
使用命名构造函数可以为一个类实现多个构造函数, 或者使用命名构造函数来更清晰的表明你的意图。
class Point {
num x;
num y;
Point(this.x, this.y);
//命名构造函数
Point.fromJson(Map json) {
x = json[‘x’];
y = json[‘y’];
}
}
重定向构造函数
一个重定向构造函数是没有代码的,在构造函数声明后,使用 冒号调用其他构造函数。
class Point {
num x;
num y;
Point(this.x, this.y);
//重定向构造函数,使用冒号调用其他构造函数
Point.alongXAxis(num x) : this(x, 0);
}
初始化列表
在构造函数体执行之前可以初始化实例参数。 使用逗号分隔初始化表达式。初始化列表非常适合用来设置 final 变量的值。
import ‘dart:math’;
class Point {
//final变量不能被修改,必须被构造函数初始化
final num x;
final num y;
final num distanceFromOrigin;
//初始化列表
Point(x, y)
: x = x,
y = y,
distanceFromOrigin = sqrt(x * x + y * y);
}
调用超类构造函数
首先来建立一个超类(父类),下面的代码都继承自此类:
class Parent {
int x;
int y;
//父类命名构造函数不会传递
Parent.fromJson(x, y)
: x = x,
y = y {
print(‘父类命名构造函数’);
}
}
- 超类命名构造函数不会传递,如果希望使用超类中定义的命名构造函数创建子类,则必须在子类中实现该构造函数。
class Child extends Parent {
int x;
int y;
-
Child.fromJson(x, y)
-
x = x,
y = y,
print(‘子类命名构造函数’);
}
}
- 如果超类没有默认构造函数, 则你需要手动的调用超类的其他构造函数,调用超类构造函数的参数无法访问 this。
class Child extends Parent {
int x;
int y;
//若超类没有默认构造函数, 需要手动调用超类其他构造函数
最后
简历首选内推方式,速度快,效率高啊!然后可以在拉钩,boss,脉脉,大街上看看。简历上写道熟悉什么技术就一定要去熟悉它,不然被问到不会很尴尬!做过什么项目,即使项目体量不大,但也一定要熟悉实现原理!不是你负责的部分,也可以看看同事是怎么实现的,换你来做你会怎么做?做过什么,会什么是广度问题,取决于项目内容。但做过什么,达到怎样一个境界,这是深度问题,和个人学习能力和解决问题的态度有关了。大公司看深度,小公司看广度。大公司面试你会的,小公司面试他们用到的你会不会,也就是岗位匹配度。
选定你想去的几家公司后,先去一些小的公司练练,学习下面试技巧,总结下,也算是熟悉下面试氛围,平时和同事或者产品PK时可以讲得头头是道,思路清晰至极,到了现场真的不一样,怎么描述你所做的一切,这绝对是个学术性问题!
面试过程一定要有礼貌!即使你觉得面试官不尊重你,经常打断你的讲解,或者你觉得他不如你,问的问题缺乏专业水平,你也一定要尊重他,谁叫现在是他选择你,等你拿到offer后就是你选择他了。
金九银十面试季,跳槽季,整理面试题已经成了我多年的习惯!在这里我和身边一些朋友特意整理了一份快速进阶为Android高级工程师的系统且全面的学习资料。涵盖了Android初级——Android高级架构师进阶必备的一些学习技能。
附上:我们之前因为秋招收集的二十套一二线互联网公司Android面试真题(含BAT、小米、华为、美团、滴滴)和我自己整理Android复习笔记(包含Android基础知识点、Android扩展知识点、Android源码解析、设计模式汇总、Gradle知识点、常见算法题汇总。)
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
就是岗位匹配度。
选定你想去的几家公司后,先去一些小的公司练练,学习下面试技巧,总结下,也算是熟悉下面试氛围,平时和同事或者产品PK时可以讲得头头是道,思路清晰至极,到了现场真的不一样,怎么描述你所做的一切,这绝对是个学术性问题!
面试过程一定要有礼貌!即使你觉得面试官不尊重你,经常打断你的讲解,或者你觉得他不如你,问的问题缺乏专业水平,你也一定要尊重他,谁叫现在是他选择你,等你拿到offer后就是你选择他了。
金九银十面试季,跳槽季,整理面试题已经成了我多年的习惯!在这里我和身边一些朋友特意整理了一份快速进阶为Android高级工程师的系统且全面的学习资料。涵盖了Android初级——Android高级架构师进阶必备的一些学习技能。
附上:我们之前因为秋招收集的二十套一二线互联网公司Android面试真题(含BAT、小米、华为、美团、滴滴)和我自己整理Android复习笔记(包含Android基础知识点、Android扩展知识点、Android源码解析、设计模式汇总、Gradle知识点、常见算法题汇总。)
[外链图片转存中…(img-BjrBPFXV-1715815276652)]
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!