一 标识符、关键字、数据类型
1.1 标识符
- Java对各种变量、方法和类等要素命名时使用的字符序列称为标识符
- 凡是自己可以起名字的地方都叫标识符,都遵守标识符的规则
- Java标识符命名规则:
- 标识符由字母、下划线"_"、美元符"$"或数字组成
- 标识符应以字母、下划线、美元符开头
- Java标识符的大小写敏感,长度无限制
- 约定俗成:Java标识符选取因注意“见名知意”且不能与Java语言的关键字重名
1.2 关键字
- Java中一些赋予特定的含义,用作专门用途的字符串称为关键字(keyword)
- 大多数编译器会将关键字用特殊方式标出
- 所有Java关键字都是小写英文
- goto和const虽然从未使用,但也作被为Java关键字保留
1.3 Java常量
常量的基本含义就是不变的东西,如
- Java的常量用字符串表示,区分为不同的数据类型
- 如整型常量 123
- 实型常量 3.14
- 字符常量 'a'
- 逻辑常量 true、false
- 字符串常量 "helloworld"
- 注意:区分字符常量和字符串常量
- 注意:“常量”这个名字还会用在另外其它语境中表示值不可变的变量
- 参见final关键字
1.4 Java变量
Java变量是程序中最基本的存储单元,其要素包括变量名,变量类型和作用域。Java程序中每一个变量都属于特定的数据类型,在使用前必须对其声明,声明格式为:
type varName [=value][{,varName[=value]}]
例如:
int i = 100;
float f = 12.3f;
double d1,d2,d3 = 0.123; //其中d1,d2表示没有设置的值,默认double为0.0;此处的d3为0.123
String s = "hello";
从本质上讲,变量其实是内存中的一小块区域,使用变量名来访问这块区域,因此,每一个变量使用前必须要先申请(声明),然后必须进行赋值(填充内容),才能使用。而这块区域的大小(内存区域的大小)是由数据类型决定的,比如int、float、double等都有不同的大小
程序的执行过程,如下图所示:
- 当硬盘上一个程序的源文件(如.exe等)运行起来,首先是装载到内存中
- 操作系统(或者Java虚拟机)开始找到main()方法(程序入口),开始运行
- 在运行的过程中,对该程序的内存空间有一个分类
- code segment:代码段,存放程序源代码使用
- data segment:数据段,存放静态变量、字符串常量
- stack:栈区,存放局部变量
- heap:堆,存放new出来的东西。稍后介绍new
1.4.1 Java变量的分类
- 按被声明的位置划分:
- 局部变量:方法或语句块内部定义的变量
- 成员变量:方法外部、类的内部定义的变量
- 注意:类外面(与类对应的大括号外面)不能有变量的声明
- 按所属的数据类型划分:
- 基本数据类型变量
- 引用数据类型变量
1.4.1.1 Java局部变量与成员变量
方法体内部的变量(包括形参)称为局部变量。方法体内部指的是方法对应的大括号部分内容
在方法体外,类体内声明的变量称为成员变量
public class HelloWorld {
int j = 9; //成员变量
public static void main(String[] args) {
System.out.println("HelloWorld");
int i = 8; //局部变量
}
}
可以简单理解为,凡是在大括号中声明的变量,出了这个大括号就无法识别了
如下一段代码
public class testVar {
static int j;
public void m() {
int i = 0;
System.out.println(i);
}
public static void main(String[] args) {
int i = 0;
System.out.println(i);
System.out.println(j);
boolean b = false;
if (b) {
int c = 0;
System.out.println("b is true");
}
long longNum1 = 88888888;
}
}
1.4.1.2 Java数据类型的划分
如下图所示:
1.4.1.2.1 基本数据类型
Java中定义了4类8种基本数据类型:
- 逻辑型 -- boolean
- 字符型 -- char
- 整数型 -- byte, short, int, long
- 浮点数型 -- float, double
1.4.1.2.1.1 逻辑型boolean
boolean类型适于逻辑运算,一般用于程序流程控制。
boolean类型数据只允许取值true或false,不可以0或者非0的整数替代true和false。
如下列代码
boolean flag;
flag = true;
if (flag) { 如果flag为true的话,执行if(){}体语句
//do something
}
1.4.1.2.1.2 字符型char
char型数据用来表示通常意义上的字符。
字符常量为用单引号括起来的单个字符,例如:
char eChar = 'a'; char cChar = '中';
- Java字符采用Unicode编码,每个字符占两个字节,因而可用十六进制编码形式表示,例如:
- char c1='\u0061';
- 注:Unicode是全球语言统一编码
- Java语言中还允许使用转义字符“\”将其后的字符变为其它的含义,例如:
- char c2='\n';
- \n表示换行符
- \r表示回车符
- \u表示后面的数字是十六进制的Unicode编码
1.4.1.2.1.3 整数类型
Java各整数类型有固定的表数范围和字段长度,其不受具体操作系统的影响,以保证Java程序的可移植性。
Java语言整型常量的三种表示形式:
- 十进制整数,如:12,-314,0
- 八进制整数,要求以0开头,如:012
- 十六进制数,要求0x或者0X开头,如:0x12
Java语言的整型常量默认为int,声明long型常量可以后加'l'或者'L',如
int i1 = 600; //正确
long i2 = 88888888888L; //必须加L,否则会出错
如下所示,是各个类型的表数范围
1.4.1.2.1.4 浮点类型
与整数类型类似,Java浮点类型有固定的表数范围和字段长度,不受平台影响。
Java浮点类型常量有两种表示方式:
- 十进制数形式,例如:3.14 314.0 .314
- 科学计数法形式,如:3.14e2 3.14E2 100E-2
Java浮点型常量默认为double型,如要声明一个常量为float型,则需在数字后面加f或者F。如
double d = 12345.6; //正确
float f = 12.3f; //必须加f,否则会出错
如下所示,是double和float表数范围
如下小程序
public class TestVar2 {
public static void main(String[] args){
boolean b = true;
int x,y = 9;
x = 12;
double d = 3.1415;
char c1,c2;
c1 = '\u534e'; c2 = 'c';
System.out.println("b=" + b);
System.out.println("x=" + x + ",y=" + y);
System.out.println("d=" + d);
System.out.println("c1=" + c1);
System.out.println("c2=" + c2);
}
}
1.5 基本数据类型转换
- boolean类型不可以转换为其他的数据类型
- 整型,字符型,浮点型的数据在混合运算中相互转换,转换时遵循以下原则
- 容量小的类型自动转换为容量大的数据类型;数据类型按容量大小排序为:
- byte,short,char->int->long->float->double
- byte,short,char之间不会互相转换,他们三者在计算时首先会转换为int类型
- 容量大的数据类型转换为容量小的数据类型时,要加上强制转换符,但可能造成精度降低或溢出;使用时要格外注意
- 有多种类型的数据混合运算时,系统首先自动的将所有数据转换成容量最大的哪一种数据类型,然后再进行计算
- 实数常量(如1.2)默认为double
- 整数常量(如123)默认为int
如下小程序
public class TestConvert {
public static void main(String[] args){
int i1 = 123;
int i2 = 456;
double d1 = (i1+i2)*1.2; //系统自动转换为double型运算
float f1 = (float)((i1+i2)*1.2); //((i1+i2)*1.2)为double型,转换为float需要强制转换:在前面加(float)
byte b1 = 1;
byte b2 = 2;
byte b3 = (byte)(b1+b2); //b1+b2系统自动转换为int型运算,所以需要强制转换
double d2 = 1e200;
float f2 = (float)d2; //强制转换,但是会溢出
System.out.println(f2);
float f3 = 1.23f; //必须加f
long l1 = 123;
long l2 = 30000000000000L; //必须加L
float f = l1+l2+f3; //系统将转换为float型计算
long l = (long)f; //强制转换会舍去小数部分(不是四舍五入)
}
}
练习:指出下列程序片段中编译出错或可能产生计算溢出的部分,并修正
public class TestConvert2 {
public static void main(String[] args){
int i = 1,j; //没有问题
float f1 = 0.1; //有问题,0.1为double类型,需要强制转换
float f2 = 123; //没有问题
long l1 = 12345678; //没有问题
long l2 = 8888888888888888; //有问题,后面数为int,需要转换
double d1 = 2e20 ; //没有问题
double d2 = 123; //没有问题
byte b1 = 1 ; //没有问题
byte b2 = 2; //没有问题
byte b3 = 129; //有问题,溢出byte,需要强制转换
j = j+10; //有问题,j没有赋值
i = i/10; //没有问题
i = i*0.1; //有问题,0.1为double类型,需要强制转换
char c1 = 'a' ; //没有问题
char c2 = 125; //没有问题
byte b = b1-b2; //有问题,b1-b2为int类型
char c = c1+c2-1; //有问题,c1+c2-1为int类型
float f3 = f1+f2; //没有问题
float f4 = f1+f2*0.1; //有问题,0.1为double类型
double d = d1*i+j; //没有问题
float f = (float)(d1*5+d2); //没有问题
}
}
修改后的代码为
public class TestConvert2 {
public static void main(String[] args){
int i = 1;
int j = 1;
float f1 = (float)(0.1); //或者0.1f;,0.1f在计算机上
//就是一个float类型,
//而(float)0.1为强制转换
float f2 = 123;
long l1 = 12345678;
long l2 = 8888888888888888L;
double d1 = 2e20;
double d2 = 123;
byte b1 = 1;
byte b2 = 2;
byte b3 = (byte)129;
j = j+10;
i = i/10;
i = (int)(i*0.1);
char c1 = 'a';
char c2 = 125;
byte b = (byte)(b1-b2);
char c = (char)(c1+c2-1);
float f3 = f1+f2;
float f4 = (float)(f1+f2*0.1);
double d = d1*i+j;
float f = (float)(d1*5+d2);
}
}
程序格式
格式注意的问题:
- 大括号对齐
- 遇到"{" 缩进
- 程序块之间加空行
- 并排语句之间加空格
- 运算符两侧加空格
- "{"前面有空格
- 成对编程
一 运算符
Java语言支持如下运算符:
- 算术运算符:+,-,*,/,%,++,--
- 关系运算符:>,<,>=,<=,==,!=
- 逻辑运算符:!,&,|,^,&&,||
- 位运算符:&,|,^,~,>>,<<,>>>
- 赋值运算符:=
- 扩展赋值运算符:+=,-=,*=,/=
- 字符串连接运算符:+
1.1 自加和自减运算符
public class Test {
public static void main(String[] args) {
int i1 = 10, i2 = 20;
int i = (i2++);
System.out.print("i=" + i); //没有println,表示不换行
System.out.println(" i2=" + i2);
i = (++i2);
System.out.print("i=" + i);
System.out.println(" i2=" + i2);
i = (--i1);
System.out.print("i=" + i);
System.out.println(" i1=" + i1);
i = (i1--);
System.out.print("i=" + i);
System.out.println(" i1=" + i1);
}
}
- int i=(i2++):表示先赋值,再运算。先是i=i2,然后i2再递增
- int i=(++i2):先运算,再赋值。先是i2递增,为21,然后再将i2赋值给i
1.2 逻辑运算符
如下所示:
- !:取反
- a&b:表示只有当a和b都为true的时候,才会true。其余为false
- a|b:当a或者b有一个为true的时候,就是true
- a^b:a亦或b,当a和b值相同,则为false;不相同为true
- a&&b:同a&b,结果没有区别,运算过程不同
- a||b:同a|b,结果没有区别,运算过程不同
如下代码
public class Test1 {
public static void main(String[] args) {
boolean a,b,c;
a = true;
b = false;
c = a & b; System.out.println(c);
c = a | b; System.out.println(c);
c = a ^ b; System.out.println(c);
c = !a; System.out.println(c);
c = a && b; System.out.println(c);
c = a || b; System.out.println(c);
}
}
如下代码:
public class Test2 {
public static void main(String[] args) {
int i=1,j=2;
boolean flag1 = (i>3)&&((i+j)>5); //第二个操作数不计算
boolean flag2 = (i<2)||((i+j)<6); //第二个操作数不计算
}
}
- i>3为false,使用&&运算,无论后面值为false或者true,结果都为false,所以后面不会进行计算
- i<2为true,使用||运算,无论后面操作数为true或者false,结果都为true,所以后面操作数不进行计算
1.3 赋值运算符与扩展赋值运算符
1.3.1 赋值运算符(=)
当“=”两侧数据类型不一致时,可以使用默认类型转换或使用强制类型转换原则进行处理,例如
long lo = 100;
int i = (int)lo;
注意:可以将整型常量直接赋值给byte、short、char等类型变量,而不需要进行强制类型转换,只要不超出其表数范围
1.3.2 扩展运算符
如下所示,运算符用法
1.4 字符串连接符
- "+"除用于算术加法运算外,还可以用于对字符串进行连接操作,如
int id = 800 + 90;
String s = "Hello" + "World";
- "+"运算符两侧的操作数中只要有一个字符串(String)类型,系统会自动将另一个操作数转换为字符串然后进行连接。如
int c = 12;
System.out.println("c=" + c);
- 当进行打印时,无论任何类型,都自动转为字符串进行打印
1.5 表达式
- 表达式是符合一定语法规则的运算符和操作数的序列
- 表达式的类型和值
- 对表达式中操作数进行运算得到的结果称为表达式的值
- 表达式值的数据类型即为表达式的类型
- 表达式的运算顺序
- 应按照运算符的优先级从高到低的顺序进行
- 优先级相同的运算符按照事先约定的结合方向进行
1.5.1 三目条件运算符
三目条件运算符,语法格式:
x?y:z
其中x为boolean类型表达式,先计算x的值,若为true,则整个三目的结果为表达式y的值,否则整个运算结果为表达式z的值
例如:
int score = 80; int x = -100;
String type = score < 60 ? "不及格" : "及格";
int flag = x > 0 ? 1 : (x == 0 ? 0 : -1);
System.out.println("type= " + type); type为"及格"
System.out.println("flag= " + flag); flag为-1