兄弟们,时隔多天,我们又见面了。今天,我们学习一下Java的一些基础语法。
一、常量
常量的定义:常量就是固定不变的量,一旦被定义,它的值就不能再被改变。通过final关键字进行修饰,是否使用static关键字根据实际情况而定。
常量的语法:
final 数据类型 常量名 = 值;
使用示例:
/**
* Java基础语法
*/
public class JavaGrammar {
static final int DAY_HOUR = 24; //声明并初始化常量
public static void main(String[] args) {
System.out.println("一月份有31天,总共有" + 31 * DAY_HOUR + "个小时");
}
}
运行结果如下:
注意:
1)常量名通常使用大写字符,如NAME,AGE等,只是编程时的一种规范。
2)必须要在常量声明时对其进行初始化,否则会编译报错
二、变量
2.1、变量的定义
定义:通俗意义上讲,变量就是可以变化的量,可以理解为变量是用来存储数据的一种容器,存储内容是可以发生改变的。
变量的定义格式有两种:
1)声明未初始化(未赋值):
权限修饰符 数据类型 变量名;
2)声明并初始化(赋值):
权限修饰符 数据类型 变量名 = 值;
使用示例:
/**
* Java基础语法
*/
public class JavaGrammar {
public static void main(String[] args) {
int a, b, c; // 声明三个int型整数:a、 b、c,
int d = 3, e = 4, f = 5; // 声明三个整数并赋予初值
System.out.println("d = " + d + ",e = " + e + ",f = " + f);
byte z = 22; // 声明并初始化 z
System.out.println("z = " + z);
String s = "张三"; // 声明并初始化字符串 s
System.out.println("s = " + s);
double pi = 3.14159; // 声明了双精度浮点型变量 pi
System.out.println("pi = " + pi);
char x = 'x'; // 声明变量 x 的值是字符 'x'。
System.out.println("x = " + x);
}
}
运行结果如下:
2.2、变量的作用范围
变量的作用范围,也叫做作用域,每个变量都是有自己的作用范围,超出这个范围后,就无法使用。
举个例子,比如张三在A村很有名气,如果到A村打听张三,人人都知道。可是跑到B村打听张三的时候,就没有人认识他了,即使碰巧B村也有个叫张三的人,这两个张三也不是同一个人了。
根据作用范围划分,变量分为局部变量和成员变量。
2.3、成员变量
1)类变量
- 类变量也称为静态变量,在类中以 static 关键字声明,但必须在方法之外。
- 静态变量储存在静态存储区。经常被声明为常量,很少单独使用 static 声明变量。静态变量初始化后不可改变。
- 静态变量在第一次被访问时创建,在程序结束时销毁。
- 默认值和实例变量相似。数值型变量默认值是 0,布尔型默认值是 false,引用类型默认值是 null。变量的值可以在声明的时候指定,也可以在构造方法中指定。此外,静态变量还可以在静态语句块中初始化。
- 静态变量可以通过:ClassName.VariableName的方式访问。
代码示例:
public class Person {
//age 是一个私有的静态变量,用来存储年龄
private static int age; //静态变量
//PERSON_NAME 是一个常量,用来存储姓名
public static final String PERSON_NAME = "张三"; //静态变量
//用来存储进度条
private static int progressBar; //静态变量
public static void main(String[] args) {
age = 25; //给age变量赋值
System.out.println(PERSON_NAME + "今年有" + age +"岁");
//循环,给progressBar赋值
for (int i = 0; i < 10; i++) {
progressBar += 10;
System.out.println(PERSON_NAME + "正在吃饭,已经完成了" + progressBar + "%");
}
}
}
运行结果如下:
2)实例变量
- 实例变量声明在一个类中,但在方法、构造方法和语句块之外;
- 当一个对象被实例化之后,每个实例变量的值就跟着确定;
- 实例变量在对象创建的时候创建,在对象被销毁的时候销毁;
- 实例变量的值应该至少被一个方法、构造方法或者语句块引用,使得外部能够通过这些方式获取实例变量信息;
- 实例变量可以声明在使用前或者使用后;
- 访问修饰符可以修饰实例变量;
- 实例变量具有默认值。数值型变量的默认值是0,布尔型变量的默认值是false,引用类型变量的默认值是null。变量的值可以在声明时指定,也可以在构造方法中指定;
- 实例变量可以直接通过变量名访问。但在静态方法以及其他类中,就应该使用完全限定名:ObejectReference.VariableName。
代码示例:
/**
* 动物类
*/
public class Animal {
public static void main(String[] args) {
//定义动物的种类
String type = "小猫"; //实例变量
//定义动物的名字
String name = "汤姆"; //实例变量
//定义年龄
int age = 3;
System.out.println("一只叫" + name + "的" + type + "今年" + age + "岁了");
}
}
运行结果如下:
2.4、局部变量
- 局部变量声明在方法、构造方法或者语句块中;
- 局部变量在方法、构造方法、或者语句块被执行的时候创建,当它们执行完成后,变量将会被销毁;
- 访问修饰符不能用于局部变量;
- 局部变量只在声明它的方法、构造方法或者语句块中可见;
- 局部变量是在栈上分配的。
- 局部变量没有默认值,所以局部变量被声明后,必须经过初始化,才可以使用。
代码示例:
/**
* 动物类
*/
public class Animal {
/**
* 获取动物信息的方法
* @param type 类型
* @param name 姓名 形参列表中的变量也是局部变量
*/
public void getMsg(String type,String name) {
int age = 0; //这是一个局部变量
age += 2;
System.out.println("一只叫" + name + "的" + type + "今年" + age + "岁了");
}
//主方法
public static void main(String[] args) {
//定义动物的种类
String type = "老鼠"; //成员变量
//定义动物的名字
String name = "杰瑞"; //成员变量
//调用获取动物信息的方法
Animal animal = new Animal();
animal.getMsg(type,name);
}
}
运行结果如下:
这里我们总结一下Java的变量:
1)在类中位置不同:
成员变量:在类中方法外。
局部变量:在方法定义中或者方法声明上。
2)在内存中的位置不同:
成员变量:在堆内存。
局部变量:在栈内存。
3)生命周期不同:
成员变量:随着对象的创建而存在,随着对象的消失而消失。
局部变量:随着方法的调用而存在,随着方法的调用完毕而消失。
4)初始化值不同:
成员变量:有默认值初始化。
局部变量:没有默认值初始化,必须定义,赋值,然后才能使用。
注意:局部变量名称可以和成员变量名称一样,在方法中使用的时候,采用的是就近原则。
为了方便理解,我们看一个例子:
/**
* 人类类
*/
public class Person {
/*
* 成员变量int类型的age
* */
static int age = 20;
/**
* 获取人类信息
* @param type 类型
* @param name 姓名
*/
public void getMsg(String type,String name) {
/*
* int类型的局部变量age
* */
int age = 18;
System.out.println("第二次打印:一位叫做" + name + "的" + type + ",今年" + age + "岁了"); //第二次打印
}
public static void main(String[] args) {
String type = "年轻人";
String name = "张三";
System.out.println("第一次打印:一位叫做" + name + "的" + type + ",今年" + age + "岁了"); //第一次打印
Person person = new Person();
person.getMsg(type,name);
}
}
再看一下运行结果:
三、数据类型转换
Java有严格的数据类型限制。数据类型是不可以轻易转换的。但在特殊情况下还是需要进行这样的操作,但必须有严格的步骤和规定。数据类型的转换方式可分为自动类型转换和强制类型转换两种。
3.1、自动类型转换
自动类型转换也叫隐式类型转换。在基本数据类型中,整数型由小转大,是可以进行自动类型转换的,整数型和浮点型可以进行自动类型转换,字符型与整数型也是兼容的。由于布尔类型boolean,只能存放true或false,与整数型及字符不兼容,因此不可能进行类型转换。
代码示例:
/**
* 演示自动类型转换
*/
public class TypeConversion {
public static void main(String[] args) {
//整数型的自动类型转换
byte b = 127;
short s = b; // byte 类型转 short 类型
int i = b + s; // 此处结果自动转换成了int类型
System.out.println("i = " + i); //打印结果:i = 254
//整数型和浮点型的自动类型转换
int num = 10;
double s2 = 3.5;
double f = num / s2; // int / double = double; 结果自动转换成了float类型
System.out.println("f = " + f); //打印结果:f = 2.857142857142857
float s3 = 4.0f;
float f2 = num / s3; // int / float = float; 结果自动转换成了float类型
System.out.println("f2 = " + f2); //打印结果:f2 = 2.5
//字符型和整数型自动类型转换
char c = 'A';
int num2 = c; //char 自动转换成 int 类型
System.out.println("num2 = " + num2); //打印结果:num2 = 65
}
}
运行结果如下:
在自动转换的时候,同时也要注意数据溢出的问题
代码示例:
/**
* 演示自动类型转换
*/
public class TypeConversion {
public static void main(String[] args) {
int i = 1000000000;
int i2 = 100;
long l = i * i2; //自动类型转换是发生数据溢出,导致结果不正确
System.out.println("l = " + l);
l = (long)i * i2; //提前将运算类型转换成long类型,避免了溢出现象
System.out.println("l = " + l);
}
}
运行结果如下:
这是因为当两个int类型数据进行相乘时,编译器并不清楚运算结果是否会超出int的取值范围,编译器会将计算出来的结果先保存在int中,此时结果就会发生数据溢出,然后编译器才会将结果转换成long类型。
想要解决这种情况,我们只要将运算的表达式在计算成结果之前,转换成大数据类型,就可以避免数据溢出的现象。
3.2、强制类型转换
根据名字就很好理解,强制类型转换就是将一种数据类型,强制转换成另一种数据类型。需注意,boolean类型是无法进行强转的。
我们已经知道,当小数据类型转到大数据类型,可以自动转换,那么大数据类型转到小数据类型时,我们就需要使用强制转换。
代码示例:
/**
* 演示强制类型转换
*/
public class TypeConversion {
public static void main(String[] args) {
/*
* int类型强制转换成byte类型,因为值并未超出byte的取值范围,因此数据未发生异常情况
* */
int num = 127;
byte b1 = (byte) num;
System.out.println("b1 = " + b1);
/*
* int类型强制转换成byte类型,因为值超出了byte类型的取值范围,所以发生了数据溢出现象,导致数据不准确
* */
int num2 = 1111;
byte b2 = (byte) num2;
System.out.println("b2 = " + b2);
/*
* double类型转换成int类型,因int类型为整数型,因此最终结果只取小数前的整数,数据发生变化
* */
double d = 10.9132156;
int num3 = (int) d;
System.out.println("num3 = " + num3);
/*
* char类型转换成byte类型
* */
char c = '中';
//'中'在字符集中的编码为20013,超过了byte的取值范围,所以强转后会发生数据溢出现象
byte b3 = (byte) c;
System.out.println("b3 = " + b3);
//而20013处于int类型的取值范围内,此处发生了自动类型转换
int l = c;
System.out.println("l = " + l);
/*
* 整数强转为字符类型,结果为整数值在编码表中所对应的字符
* */
byte b4 = 45;
char c2 = (char) b4;
System.out.println("c2 = " + c2);
int l2 = 20013;
char c3 = (char) l2;
System.out.println("c3 = " + c3);
}
}
运行结果如下:
注意:强制类型转换需要谨慎使用,有可能会发生数据溢出等情况,导致得到无意义的结果。