JavaSE基础——基础语法2:变量、运算符
文章目录
三、变量、常量、作用域
1.变量
在Java
语言中,变量是程序中最基本的存储单元。由于强类型语言的特点,所有的变量在使用前必须声明。声明变量的基本格式如下:
type identifier [ = value][, identifier [= value] ...] ;//数据类型 变量名 = 值;可以使用逗号隔开来声明多个同类型的变量。//不过不提倡在一行声明多个变量,可读性不好。
注意事项
- 变量的基本要素包括变量名,变量类型和作用域
- 每个变量都有类型,类型可以是基本类型也可以是引用类型
- 变量名必须是合法的标识符
- 变量声明是一条完整的语句,因此每个声明都必须以分号结束。
2.常量
常量初始化之后就不能再改变值。即在程序运行时是不能被修改的。
在 Java
中使用 final
关键字来修饰常量,声明方式和变量类似。为了便于识别,通常使用大写字母表示常量。
final double PI = 3.14; /*1.常量使用关键字final2.常量的声明方式和变量类似3.常量的命名通常用大写字母,不同含义的单词之间用下划线,如MY_VALUE
3.作用域
Java语言支持的变量类型有:
- 类变量:独立于方法之外的变量,用 static 修饰。
- 实例变量:独立于方法之外的变量,不过没有 static 修饰。
- 局部变量:类的方法中的变量。
//变量、常量与作用域
public class Demo02 { //class关键字,类名Demo02
static int allClicks = 0; //类变量。在类方法之外,用static修饰
String str = "Hello World!"; //实例变量。在类方法之外,没有static修饰。
//String是类名称,str是String类的一个实例对象
public static void main(String[] args) {
int i = 0; //局部变量。main是class的方法,类的方法中的变量即局部变量
}
}
3.1 局部变量
- 局部变量声明在方法、构造方法或者语句块中;
- 局部变量在方法、构造方法、或者语句块被执行的时候创建,当它们执行完成后,变量将会被销毁;
- 访问修饰符不能用于局部变量;
- 局部变量只在声明它的方法、构造方法或者语句块中可见;
- 局部变量是在栈上分配的。
- 局部变量没有默认值,所以局部变量被声明后,必须经过初始化,才可以使用。
3.2 实例变量
- 实例变量声明在一个类中,但在方法、构造方法和语句块之外;
- 当一个对象被实例化之后,每个实例变量的值就跟着确定;
- 实例变量在对象创建的时候创建,在对象被销毁的时候销毁;
- 实例变量的值应该至少被一个方法、构造方法或者语句块引用,使得外部能够通过这些方式获取实例变量信息;
- 实例变量可以声明在使用前或者使用后;
- 访问修饰符可以修饰实例变量;
- 实例变量对于类中的方法、构造方法或者语句块是可见的。一般情况下应该把实例变量设为私有。通过使用访问修饰符可以使实例变量对子类可见;
- 实例变量具有默认值。数值型变量的默认值是0,布尔型变量的默认值是false,引用类型变量的默认值是null。变量的值可以在声明时指定,也可以在构造方法中指定;
- 实例变量可以直接通过变量名访问。但在静态方法以及其他类中,就应该使用完全限定名:ObejectReference.VariableName。
3.3 类变量(静态变量)
- 类变量也称为静态变量,在类中以 static 关键字声明,但必须在方法之外。
- 无论一个类创建了多少个对象,类只拥有类变量的一份拷贝。
- 静态变量除了被声明为常量外很少使用,静态变量是指声明为 public/private,final 和 static 类型的变量。静态变量初始化后不可改变。
- 静态变量储存在静态存储区。经常被声明为常量,很少单独使用 static 声明变量。
- 静态变量在第一次被访问时创建,在程序结束时销毁。
- 与实例变量具有相似的可见性。但为了对类的使用者可见,大多数静态变量声明为 public 类型。
- 默认值和实例变量相似。数值型变量默认值是 0,布尔型默认值是 false,引用类型默认值是 null。变量的值可以在声明的时候指定,也可以在构造方法中指定。此外,静态变量还可以在静态语句块中初始化。
- 静态变量可以通过:ClassName.VariableName的方式访问。
- 类变量被声明为 public static final 类型时,类变量名称一般建议使用大写字母。如果静态变量不是 public 和 final 类型,其命名方式与实例变量以及局部变量的命名方式一致。
//类变量、实例变量和局部变量
public class Demo02 { //创建了一个类Demo02
//通过类可以实例出类对象,因此类可以看作是创建对象的模板
//类里面主要包括属性和方法,比如所有类里都会有的main()方法
/*类变量(也称静态变量):在类方法之外,用static修饰
1.从属于类,随着类一起出现或消失
2.存储在静态存储区,除了被声明为常量外很少使用。静态变量初始化后不可改变
3.与实例变量的可见性相同,即对类中的方法、语句块均可见,不过一般为public型
4.默认值与实例变量相同
5.可以通过ClassName.VariableName的方式访问
*/
public static final String DEPARTMENT = "automan"; //声明类变量DEPARTMENT
//若其他类想使用该DEPATMENT变量,可以使用Demo02.DEPARTMENT访问
private final static double PI = 3.14; //私有类常量,标识符不分先后顺序
/*实例变量:在类方法之外,没有static修饰。
1.从属于对象,当对象被实例化后,实例变量的值就随之确定,随着实例对象一起出现或消失
2.实例变量可以声明在使用前或使用后
3.访问修饰符可以修饰实例变量
4.实例变量由默认值,数值型变量默认为0,boolean型变量默认为false,引用型变量默认为null
5.实例变量对于类中的方法、语句块等是可见的,但一般应设为私有,通过访问修饰符使必要的子类可见
*/
private double salary; //创建私有实例变量
public void setSalary (double empSal){ //创建setSalary方法,用于给实例变量salary赋值
salary = empSal;
}
public void printEmp(){ //创建printEmp方法,用于访问类变量DEPARTMENT和实例变量salary,并输出结果
System.out.println(DEPARTMENT + "的薪水是:" + salary);
}
public static void main(String[] args) {
/*局部变量:类的方法中的变量
1.局部变量没有默认值,必须声明和初始化值;
2.局部变量声明在方法或语句块中,其作用范围和生命周期限于所在的代码块内
3.访问修饰符不能用于局部变量
4.局部变量是在栈上分配的。栈是动态内存区域,后入先出。
*/
int age = 0;
age += 7;
System.out.println(DEPARTMENT + "的年龄是:" + age); //输出局部变量
Demo02 empOne = new Demo02(); //new一个新类,名称为empOne
empOne.setSalary(1000); //调用类中的setSalary方法,用到类变量
empOne.printEmp(); //调用类中的printEmp方法,用到了类变量和实例变量,并输出结果
}
}
-----------------------------------
运行结果:
automan的年龄是:7
automan的薪水是:1000.0
4.变量命名规范
- 所有变量、方法、类名:见名知意
- 类成员变量:首字母小写和驼峰原则:monthSalary
- 局部变量:首字母小写和驼峰原则
- 常量:大写字母和下划线:MAX_VALUE
- 类名:首字母大写和驼峰原则:HelloWorld
- 方法名:首字母小写和驼峰原则:runRun()
四、运算符
计算机的最基本用途之一就是执行数学运算,作为一门计算机语言,Java也提供了以下几种运算符:
- 算术运算符: +,-, *, /, %, ++, —
- 赋值运算符:=
- 关系运算符:>, <, >=, <=, **, !=,instanceof
- 逻辑运算符:&&(与) ,||(或), !(非)
- 位运算符:&,|,^,~,>>, <<,>>>
- 其他运算符
1.算数运算符、赋值运算符
//基本运算符及数据类型复习
public class Demo03 {
public static void main(String[] args) {
//二元运算符:作用对象为两个操作数
int a = 10;
int b = 20;
int c = 25;
int d = 25;
System.out.println(a + b);
System.out.println(a - b);
System.out.println(a * b);
System.out.println(a / b); //由于两个操作数都是int型,因此结果也是int型,对于浮点数转int型,直接舍去小数部分,结果为0
System.out.println(a / (double)b); //为获取正确结果,需对操作数进行强制类型转换,结果类型会自动转为操作数中级别最高的类型
System.out.println(c % a); //取余运算,又称取模运算
System.out.println("----------------------");
double x = 23;
long y = 1231231231231112L;
int z = 123;
short m = 10;
byte n = 8;
System.out.println(x + y + z + m + n); //结果为double类型
System.out.println(y + z + m + n); //结果为long类型
System.out.println(z + m + n); //结果为int类型
System.out.println(m + n); //结果为int类型; short + byte = short,但整数默认是int型,因此自动转换为int
System.out.println("----------------------");
//一元运算符:作用对象只有一个操作数
//自增自减运算符:++ --
int num1 = 5; //定义一个变量;
int num2 = 5;
int num3 = ++num1; //自增运算
int num4 = --num2; //自减运算
System.out.println("进行自增运算后的值 = " + num3); //自增运算符的结果是使数值加1
System.out.println("进行自减运算后的值 = " + num4); //自减运算符的结果是使数值减1
System.out.println("当前num1的值 = " + num1);
System.out.println("当前num2的值 = " + num2);
int num5 = 2 * ++num1; //前缀自增自减运算符是先进行自增自减运算,在进行表达式运算
//即该表达式相当于:num1 = num1 + 1 = 6 + 1 = 7; num5 = 2 * num1 = 2 * 7 = 14
int num6 = 2 * num2++; //后缀自增自减运算符是先进行表达式运算,在进行自增自减运算
//即该表达式相当于:num6 = 2 * num2 = 2 * 4 = 8; num2 = num2 + 1 = 4 + 1 = 5
System.out.println("自增运算符前缀运算后num5 = " + num5 + ",num1 = " + num1);
System.out.println("自增运算符后缀运算后num6 = " + num6 + ",num2 = " + num2);
}
}
-----------------------------------
运行结果:
30
-10
200
0
0.5
5
----------------------
1.231231231231276E15
1231231231231253
141
18
----------------------
进行自增运算后的值 = 6
进行自减运算后的值 = 4
当前num1的值 = 6
当前num2的值 = 4
自增运算符前缀运算后num5 = 14,num1 = 7
自增运算符后缀运算后num6 = 8,num2 = 5
2.逻辑运算符、关系运算符
//逻辑运算符、位运算符、其他运算符
public class Demo04 {
public static void main(String[] args) {
//逻辑运算符:&&(与)、 ||(或)、 !(非)
boolean a = true;
boolean b = false;
System.out.println("a && b = " + (a && b)); //逻辑与:同真则真,有假则假
System.out.println("a || b = " + (a || b) ); //逻辑或:同假则假,有真则真
System.out.println("!(a && b) = " + !(a && b)); //逻辑非:遇真则假,遇假则真
/*
短路运算:
当使用与逻辑运算符时,在两个操作数都为true时,结果才为true,
但是当得到第一个操作为false时,其结果就必定是false,这时候就不会再判断第二个操作了。
*/
int c = 5;
boolean d = (c < 4) && (c++ < 10); //逻辑与:同真则真,有假则假;
//现在(c < 4)为假,d已经可以判断为假,根据短路运算原则,系统将不再执行后面的(d++ < 10)
System.out.println("使用短路逻辑运算符的结果为" + c); //由c的结果可以判断(d++ < 10)是否执行,若执行,c的值将加1
System.out.println("d的结果为" + d);
System.out.println("----------------------------");
//&与|是位运算符,但用于boolean类型的数值结果也是boolean类型,和&&、||唯一的区别就是&、|不按短路计算。
d = (c < 4) & (c++ < 10);
System.out.println("未使用短路逻辑运算符的结果为" + c); //根据c的结果可以判断(d++ < 10)已执行,c的值将加1
System.out.println("d的结果为" + d); //&作用于boolean值的效果与&&相同,只是不进行短路运算。|也是如此。
}
}
-------------------------------------
运行结果:
a && b = false
a || b = true
!(a && b) = true
使用短路逻辑运算符的结果为5
d的结果为false
----------------------------
未使用短路逻辑运算符的结果为6
d的结果为false
3.位运算符
//位运算符:按位运算,即二进制的位
public class Demo05 {
public static void main(String[] args) {
int a = 60; // 60 = 0011 1100
int b = 13; // 13 = 0000 1101
int c = 0;
c = a & b; //& 与运算:对应位都是1,则结果为1,否则为0
System.out.println("a & b = " + c ); // c = 0000 1100 = 12
c = a | b; //| 或运算:对应位都是 0,则结果为 0,否则为 1
System.out.println("a | b = " + c ); // c = 0011 1101 = 32+16+8+4+1 = 61
//&与|用于boolean类型的数值结果也是boolean类型,和&&、||唯一的区别就是&、|不按短路计算。
c = a ^ b; //^ 异或:对应位值相同,则结果为0,否则为1
System.out.println("a ^ b = " + c ); // c = 0011 0001 = 32+16+1 = 49
c = ~a; //~ 取反:按位取反运算符翻转操作数的每一位,即0变成1,1变成0。
System.out.println("~a = " + c ); // c = 1100 0011 = -2^7+2^6+2^1+1 = -61
//int类型是带符号位的,补码形式,最高位为符号位。
c = a << 2; //<< 按位左移:左操作数按位左移右操作数指定的位数
System.out.println("a << 2 = " + c ); // a = 0011 1100 所有位左移两位,空余补0。即:1111 0000 = 128+64+32+16 = 240
c = a >> 2; //>> 按位右移:左操作数按位右移右操作数指定的位数
System.out.println("a >> 2 = " + c ); // a = 0011 1100 所有位右移两位,空余补0。即:0000 1111 = 8+4+2+1 = 15
c = a >>> 2; //>>> 按位右移补零:左操作数的值按右操作数指定的位数右移,移动得到的空位以零填充。
System.out.println("a >>> 2 = " + c ); // a = 0011 1100 所有位右移两位,空余补0。即:0000 1111 = 8+4+2+1 = 15
//位运算速度极快,且左移(<<)相当于乘2,右移(>>)相当于除2
//如何快速运算8*4 8/4 ——位运算
System.out.println(8<<2);//8 = 0000 1000 左移两位变为 0010 0000 = 32;相当于8 * 2 * 2 = 32
System.out.println(8>>2);//8 = 0000 1000 右移两位变为 0000 0010 = 2;相当于8 / 2 / 2 = 2
}
}
---------------------------------------
运行结果:
a & b = 12
a | b = 61
a ^ b = 49
~a = -61
a << 2 = 240
a >> 2 = 15
a >>> 2 = 15
32
2
4.其他运算符
//其他运算符:扩展赋值运算符、字符串连接符、条件运算符、
public class Demo06 {
public static void main(String[] args) {
//扩展赋值运算符
int a = 20;
int b = 10;
a += b; //即 a = a + b;
System.out.println(a);
a -= b; //即 a = a - b;
System.out.println(a);
a *= b; //即 a = a * b;
System.out.println(a);
a /= b; //即 a = a / b;
System.out.println(a);
System.out.println("-----------------------------");
//字符串连接符 +
System.out.println("" + a + b);
System.out.println(a + b + "");
System.out.println("-----------------------------");
//条件运算符(三目运算符)
//x ? y : z
//若x ** true,则结果为y,否则结果为z
int score = 80;
String type = score < 60 ? "不及格" : "及格";
System.out.println(type);
System.out.println("-----------------------------");
//insteadof运算符:用于操作对象实例,检查该对象是否是一个特定类型(类类型或接口类型)
//( Object reference variable ) instanceof (class/interface type)
String name = "James";
boolean result = name instanceof String; // 由于 name 是 String 类型,所以返回真
System.out.println(result);
}
}
---------------------------------
运行结果:
30
20
200
20
-----------------------------
2010
30
-----------------------------
及格
-----------------------------
true
补充:基本数据类型和引用数据类型
Java中的数据类型分为两大类,基本数据类型和引用数据类型。
1、基本数据类型
基本数据类型只有8种,可按照如下分类
①整数类型:long、int、short、byte
②浮点类型:float、double
③字符类型:char
④布尔类型:boolean
2、引用数据类型
引用数据类型非常多,大致包括:
类、 接口类型、 数组类型、 枚举类型、 注解类型、 字符串型
例如,String
类型就是引用类型。
简单来说,所有的非基本数据类型都是引用数据类型。
3、基本数据类型和引用数据类型的区别
存储位置
基本变量类型
- 在方法中定义的非全局基本数据类型变量的具体内容是存储在栈中的
引用变量类型
- 只要是引用数据类型变量,其具体内容都是存放在堆中的,而栈中存放的是其具体内容所在内存的地址
ps:通过变量地址可以找到变量的具体内容,就如同通过房间号可以找到房间一般