1 空值,不等于零 有哪些类型
1.1 常见数据类型对应需要判断的值
1.1 基本数据类型
注意:java的8大基本数据类型只有 不等于0判断,没有非空(null)判断。因为基本类型的取值范围不包含null。
默认值:
- 整数类型int、byte、short、long的默认值为:0
- 带小数点的float、double默认值为:0.0
- boolean的默认值为:false
- char的默认值是:
/u0000
(默认值,一般不显示。空白符的code是0x20,0x20以下是不可见得控制字符。某些系统在遇到不可见字符时会输出一个方框表示遇到了不可见字符)
基本类型的非0判断的意义:数据是否被有效赋值的判断在很多情况下也是必要的
。
1.2 引用数据类型
默认值:null
引用类型的非null的判断的意义:防止出现空指针异常
,当我们去调用这个未赋值变量的方法,或者访问其内部变量的时候就会抛出空指针异常。
1.2.1 String (null和0的区别)
注意:String类型虽然也是引用类型,但是需要判断 不等于0,非空(null)判断。
对象中0和null的区别:
Objext ob = new Object();
ob = null; //对象为空,连地址值都没有
ob = 0; //有对象地址值,但是存的值为0
默认值:null
意义:非空判断防止出现空指针,长度大于0可以避免是一个空串""
//注意:这种写法 s == null是必要且必须在前面的,否则会因为null调用方法而抛出空指针异常。
if(s == null || s.length() <= 0){
......} //s是一个String类型
1.3 容器类
1.3.1、 数组
默认值:
- 声明但不定义长度,值为null
- 长度为0数组,不为null,但注意不可直接取出元素,会抛出索引越界错误(ArrayIndexOutOfBoundsException)
- 基本类型数组声明且定义长度,但不赋值,所有元素值为该基本类型默认值
- 引用类型数组声明且定义长度,但不赋值,所有元素为null
int[] arrayNull; //值为null
int[] arrayZero = new int[0]; //值为{}
int[] arrayInt = new int[2]; //值为{0,0}
Object[] arrayObj = new Object[2]; //值为{null,null}
说明:可以进行非空和长度不等于0判断
null和0的区别???
1.3.2、 集合
- 不赋值的情况下为null
- List:允许重复元素,可以加入任意多个null。
- Set:不允许重复元素,最多可以加入一个null。
- Map:Map的key最多可以加入一个null,value字段没有限制。
说明:可以进行非空判断。
2. 为什么要做空判断
说明:让程序具有健壮性还有防御性
2.1、避免空指针异常
在定义变量而不赋值的情况下,除了基本数据类型,其他类型变量都会默认为null。
null也可以认为是除基本数据类型外其他类型的默认值,所以一个含参数的方法,只要参数不为基本数据类型,在调用时都可以填入null为参数。
public void funcString(String s) {
s.isEmpty();
}
//在main方法中调用
funcString(null); //参数传入null IDE并不会报错 可以进行编译
//运行后会抛出NullPointerException
可以看出null作为参数传入方法,但是一旦传入null,内部相当于进行了这一过程null.isEmpty();报错也就很正常了。
所以类似这种需要对对象的方法进行方法调用的情况加一个非空判断就非常必要了。
再举一个比较实际的例子:
假设服务器返回这样的一段json数据
{
"id": 5,
"title": "我是文章标题",
"comment": {
"userid": 4,
"content": "我是评论内容~~~"
}
}
现在把它映射成这样的一个对象
public class Article {
private int id; //文章id
private String title;//文章标题
private Comment comment;//文章评论
class Comment {
//内部对象“评论”
private int userId;//评论用户Id
private String content;//评论内容
public int getUserId() {
return userId;
}
public void setUserId(int userId) {
this.userId = userId;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public Comment getComment() {
return comment;
}
public void setComment(Comment comment) {
this.comment = comment;
}
}
以安卓最基本的控件TextView为例,我们现在把文章评论的内容显示出来
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = (TextView) findViewById(R.id.txt);
String commentContent=getArticle().getComment().getContent();
textView.setText(commentContent);
}
public Article getArticle(){
//获取数据 映射成Article对象 并返回
}
以上的例子并没有加入非空判断,而文章评论也顺利的显示出来了
但是,如果一篇刚发布的文章,看到的人可能都没几个,又怎么会有评论呢?服务器返回的数据很可能是这样的:
{
"id": 6,
"title": "我是文章标题",
"comment": {
}
}
这时这段代码
String commentContent=getArticle().getComment().getContent();
运行时就变成了
String commentContent=null.getContent();
所以必须加入非空判断:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = (TextView) findViewById(R.id.txt);
if (getArticle().getComment()!=null){
String commentContent=getArticle().getComment().getContent();
textView.setText(commentContent);
}
}
2.2、增加程序性能
同样以上面的例子来说,这段代码
String commentContent=getArticle().getComment().getContent();
也可以通过try catch语句来捕捉空指针异常并进行处理
但是通过非空判断的方式,当程序运行到if (getArticle().getComment()!=null),就不再继续进行,从性能的角度说也更合适。
3. 用return减少嵌套
使用非空判断的时候因为要使用到if–else语句,不免要多出一些嵌套,当逻辑比较简单的时候还好,如果复杂一点的逻辑就可能要使用到多重嵌套,看着一堆迷之缩进是很影响代码可读性的,所以从小养成用return语句减少嵌套的习惯是很重要的。
继续优化上面那段代码:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = (TextView) findViewById(R.id.txt);
if (getArticle().getComment() == null) return; //把判断条件改为相反 一旦符合return结束方法
String commentContent = getArticle().getComment().getContent();
textView.setText(commentContent);
}
使用return后少了一对花括号,在这个例子里可能看不出太大好处,但是在一些复杂判断多重嵌套下,使用return可以明显提升代码可读性。
另外需要用else的时候也可以这样:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = (TextView) findViewById(R.id.txt);
if (getArticle().getComment() == null) {
//把else里的语句 放到里面 最后加上return 跳过后面语句
textView.setText("暂时没有评论");
return;
}
String commentContent = getArticle().getComment().getContent();
textView.setText(commentContent);
4 总结
主要还是理清你写的方法接收的参数或者是Api接收的数据是什么类型,有哪些可能性。然后对症下药去写判断就行啦~~