程序跑起来后运行结果却有BUG?

0X01 前言

对于有些编程经验的小伙伴来说,当他学过一门编程语言后,再去学习其他语言时,都会感觉这和某某语言很相似,貌似感觉都会,于是针对初期的基础知识学习也就会眼高手低,那么其实这些编程语言的基础语法知识到底有多重要呢?通过后期大量的写各种代码和实战写项目,就会发现其实有时候的BUG就是那些学习基础知识的盲区导致的,由于程序可用正常跑起来,但运行结果却始终不对,这种问题一般也很难发现。先看两段代码体会体会!

0X02 你的代码

  • 代码一
class Student{
	private int id;
	private String name;
	private int age;
	
	void print(){
		System.out.println(this.id + '\n' + this.name + '\n' + this.age);
	}
	public static void main(String [] arg){
		Student xm = new Student();
		xm.id = 10086;
		xm.name = "小明";
		xm.age = 18;
		xm.print();
	}
}

上面代码执行后结果是什么呢?

预期结果:

10086
小明
18

实际结果:

10096小明
18
  • 代码二
class TestBug {
	public static void main(String[] args) {
		String a = "Hello";
		// \u000d a="world";
		System.out.println(a);
		// \u000a a="hello world!";
		System.out.println(a);
	}
}

上面的代码运行结果是什么呢?注释真的不会执行吗?

预期结果:

Hello
Hello

实际结果:

world
hello world!

 

0X03 BUG分析

通过观察代码一的执行结果可以发现,在打印语句处出现了两个问题:

  • 学生id打印结果不正确,应该为10086却加了10打印出来了10096
  • 学生id打印后换行符未能正常打印,直接打印出来了学生姓名

说到这里,你应该能够知道问题出现在了哪。

Java语法基础知识恶补

在Java语言中,数据类型分为基本数据类型和引用数据类型。其中基本数据类型又可以分为数值型、字符型和布尔型。

数值型包括:整数类型(byte、short、int、long);浮点类型(float、double);其中Java的整型常量默认为 int 型,Java 的浮点型常量默认为double型。

字符型(char)数据用来表示通常意义上“字符”(2字节),字符型常量的三种表现形式:

  • 字符常量是用单引号(‘ ’)括起来的单个字符,涵盖世界上所有书面语的字符。例如:char c1 = 'a'; char c2 = '中'; char c3 = '9';
  • Java中还允许使用转义字符‘\’来将其后的字符转变为特殊字符型常量。例如:char c3 = ‘\n’; // ‘\n’表示换行符
  • 直接使用 Unicode 值来表示字符型常量:‘\uXXXX’。其中,XXXX代表一个十六进制整数。例如:\u000a 表示 \n。

char类型是可以进行运算的。因为它都对应有Unicode码。

boolean 类型适于逻辑运算,一般用于程序流程控制,只允许取值true和false,无null。

不可以0或非 0 的整数替代false和true,这点和C语言不同。

基本数据类型转换

自动类型转换:容量小的类型自动转换为容量大的数据类型。

有多种类型的数据混合运算时,系统首先自动将所有数据转换成容量最大的那种数据类型,然后再进行计算。

byte,short,char之间不会相互转换,他们三者在计算时首先转换为int类型。

当把任何基本类型的值和字符串值进行连接运算时(+),基本类型的值将自动转化为字符串类型。

强制类型转换:自动类型转换的逆过程,将容量大的数据类型转换为容量小的数据类型。使用时要加上强制转换符 (),但可能造成精度降低或溢出,格外要注意。

所以,上面的打印语句中,在执行this.id + '\n'时,因为id为int型,转移字符'\n'为char类型,在进行+运算时会自动转换为int类型与之相加。通过下面强制类型转换我们可以发现转移字符'\n'转换为int类型后为10.

class TestBug {
	public static void main(String[] args) {
		char c = '\n';
		System.out.println((int)c);
	}
}

//10

于是执行打印语句时,就会把10086与10相加得到的值10096,再和字符串姓名相连接打印出来。

通常,字符串不能直接转换为基本类型,但通过基本类型对应的包装类则可以实现把字符串转换成基本类型。

如:String a = “43”; int i = Integer.parseInt(a);

boolean类型不可以转换为其它的数据类型。

 

通过观察代码二的执行结果可以发现,注释中的Hello World被打印了。

众所周知,在计算机内部,所有数据都使用二进制表示。那么如何简便的将现实世界常用的字符在计算机中表示呢?于是就有了各种编码。

上个世纪60年代,美国制定了一套字符编码,对英语字符与二进制位之间的关系,做了统一规定。这被称为ASCII码。ASCII码一共规定了128个字符的编码,比如空格“SPACE”是32(二进制00100000),大写的字母A是65(二进制01000001)。这128个符号(包括32个不能打印出来的控制符号),只占用了一个字节的后面7位,最前面的1位统一规定为0。

这种编码涵盖的字符太有限了,因为是美国人规定的,所以只有他们常用的英文字母和一些特殊字符。但是对于不同国家语言很显然就不适用了,于是就出现了各种各样的编码。

世界上存在着多种编码方式,同一个二进制数字可以被解释成不同的符号。因此,要想打开一个文本文件,就必须知道它的编码方式,否则用错误的编码方式解读,就会出现乱码。

后来有了Unicode这种编码,将世界上所有的符号都纳入其中。每一个符号都给予一个独一无二的编码,使用 Unicode 没有乱码的问题。

在Java中,JVM内部,所有的字符都是用Unicode编码的。

于是在处理上面代码二时,注释中的\u000a正好对应字符‘\n’,\u000d正好对应字符‘\r’,于是jvm就会执行相应操作。代码就变成了:

class TestBug {
	public static void main(String[] args) {
		String a = "Hello";
		// 
        a="world";
		System.out.println(a);
		// 
        a="hello world!";
		System.out.println(a);
	}
}

所以,Java的编译器不仅会去编译代码,也会去解析Unicode字符。

0X04 总结

通过上面两个小示例,大家应该也能体会到学习编程语言的基础语法知识的重要性,其实通过日常写的代码,不难发现用到的不就是这些简单的基础知识吗,比如三大控制结构,字符处理,字符串处理等等。正所谓"树高千尺,营养还在根部",正是这个道理吧!

0X05 微信关注

 

本站为非盈利性站点,所有资源、文章等仅供学习参考,并不贩卖软件且不存在任何商业目的及用途,如果您访问和下载某文件,表示您同意只将此文件用于参考、学习而非其他用途。
本站所发布的一切软件资源、文章内容、页面内容可能整理来自于互联网,在此郑重声明本站仅限用于学习和研究目的;并告知用户不得将上述内容用于商业或者非法用途,否则一切后果请用户自负。
如果本站相关内容有侵犯到您的合法权益,请仔细阅读本站公布的投诉指引页相关内容联系我,依法依规进行处理!
作者:理想
链接:https://www.imyjs.cn/archives/203
THE END
二维码
程序跑起来后运行结果却有BUG?
0X01 前言 对于有些编程经验的小伙伴来说,当他学过……
<<上一篇
下一篇>>
文章目录
关闭
目 录