赞
踩
Java学习笔记是一个持续更新的系列,工作多年,抽个空对自身知识做一个梳理和总结归纳,温故而知新,同时也希望能帮助到更多正在学习Java 的同学们。
本系列目录
入门篇
基础篇
变量是内存中的一个存储区域,用于在内存中保存数据,该区域的数据可以在一类型范围内不断变化,是Java程序中最基本的存储单元,包含变量类型,变量名,变量的值。
变量来源于数学,是计算机语言中能储存计算结果或能表示值的抽象概念。
使用IDEA,打开HelloWrod.java文件,我们把输出的字符串替换成一个字符串类型的变量试试
public static void main(String[] args) {
String value="Hello Word!";
System.out.println(value);
}
变量的声明就是申请内存来存储值,需要根据它的数据类型为变量分配存储空间,在Java语言中,变量的声明必须遵守以下规则
必须指定变量的数据类型
由于Java中不同的数据类型,分配的内存空间不同,所以定义的变量必须指定数据类型。
例如:String value;
必须为变量指定一个标识符
为了方便的引用变量的值,需要给变量起一个名字,遵守标识符的命名规则即可。
例如:在班级里,需要统计本班学生的数学分数,则需要学生的姓名,分数
String name; //姓名
double score=0;//分数
先声明,后使用
变量必须先定义才能使用,如果未定义则无法通过编译。
错误示范:
System.out.println(value);
String value="Hello Word!";
注意:如果是先声明,后使用,那么引用类型的变量在使用时需要进行空指针判断,可增加程序的容错性。
只在作用域内生效
变量只在定义的{}
内生效
错误示范:
public static void main(String[] args) {
System.out.println(value);//调用value
}
public void test(){
String value="Hello Word!";//声明value
}
注意:{{}}
嵌套的情况下,最外层的变量可以作用在内层{}
中,但是对变量的访问修饰符具有一定要求。
变量的作用域由声明它的位置决定,根据声明的位置,可以概述为以下三种:
static
关键字定义好的一类变量,通常在静态类中,方法外面,通过类名调用,有默认初始值。生存期即生命周期,是指变量的内存分配与回收的过程,通常根据变量的作用域决定自身的生命周期。
我们已经知道Java语言编译的程序都必须运行在JVM虚拟机中,而JVM虚拟机运行时的数据区如下
可以看出来不同作用域的变量,所处的JVM区域也不同
Java中的常量指在程序的整个运行过程中值保持不变的量。
在实际的程序中,可以根据数据在程序运行中是否发生改变,来选择应该是使用变量还是常量。
常量在程序运行过程中主要有2个作用
常量的语法格式和变量类型
只需要在变量的语法格式前面添加关键字final
即可。
常量的语法格式如下
final 数据类型 常量名称 = 值;
final 数据类型 常量名称1 = 值1, 常量名称2 = 值2,……常量名称n = 值n;
例如:
final double PI = 3.14;
final char MALE=‘M’,FEMALE=‘F’;
在Java语法中,常量也可以首先声明,然后再进行赋值,但是只能赋值一次。
final int UP;
UP = 1;
final 用于声明属性(常量),方法和类,分别表示属性一旦被分配内存空间就必须初始化
不会有默认初始化,局部变量也是如此,默认初始化只有普通的非final成员属性,对于static(无final修饰)类变量,类连接时候有默认初始化,对于像
private int a;
在类实例化时,构造函数默认初始为0,总之,变量必须初始化后方可用,这是java的安全之一。
final这个关键字的含义是“这是无法改变的”或者“最终态的”。
那么为什么要阻止改变呢?
Java语言的发明者可能由于两个目的而阻止改变:
修饰变量:
final成员变量表示常量,只能被赋值一次,赋值后值不再改变。
修饰方法:
final方法不能被子类方法覆盖,但可以被继承。
修饰类:
final类不能被继承,没有子类,final类中所有方法都是final的。(如String类)
被final修饰而没有被static修饰的类的属性变量只能在两种情况下初始化(必须初始化):
解释
当这个属性被修饰为final,而非static的时候,它属于类的实例对象的资源(实例常量),当类被加载进内存的时候这个属性并没有给其分配内存空间,而只是 定义了一个变量a,只有当类被实例化的时候这个属性才被分配内存空间。
而实例化的时候同时执行了构造函数,所以属性被初始化了,也就符合了当它被分配内存空间的时候就需要初始化,以后不再改变的条件。
被static修饰而没有被final修饰的类的属性变量只能在两种情况下初始化(可以不初始化):
解释
当类的属性被同时被修饰为static时候,他属于类的资源(类变量),在类加载后,进行连接时候,分三步:
- 先验证;然后准备,准备时,先分配内存。
- 接着默认初始化;可以进行解析。
- 最后,进行类初始化,类初始化前,必须保证它的父类已经初始化了,所以最先初始化的是超类,对于接口,不必初始其父接口。
类初始化时,它把类变量初始化语句及静态初始化语句放到类初始化方法中,所以,如果无此两种语句,也就没类初始化方法,而构造函数是在当类被实例化的时候才会执行,所以用构造函数,这时候这个属性没有被初始化,程序就会报错,而static块是类被加载的时候执行,且只执行这一次,所以在 static块中可以被初始化。
同时被final和static修饰的类的属性变量只能在两种情况下初始化(必须初始化):
class A{
private final static A a;
static{
try{
a=new A();
}catch(Exception e){
throws new RuntimeException(e); //必须有,不然不能完成常量的正确初始化
}
}
private A() throws Exception{}
}
解释
当类的属性被同时被修饰为static和final的时候,他属于类的资源(类常量),那么就是类在被加载进内存的时候(也就是应用程 序启动的时候)就要已经为此属性分配了内存。
所以此时属性已经存在,它又被final修饰,所以必须在属性定义了以后就给其初始化值。
而构造函数是在当类被实例化的时候才会执行,所以用构造函数,这时候这个属性没有被初始化,程序就会报错。
而static块是类被加载的时候执行,且只执行这一次,所以在static块中可以被初始化。
final变量的变与不变
final表示变量的值或引用不变
有人说final变量在赋值后就不可变,此变量可以是基本数据类型+String或者是对象
那么这个不变到底指的是什么呢?
这个不变指的是引用,是地址,而所引用的对象的内容仍然是可变的。
注:如果是对象,注意此时类初始化条件
就是说,这个final变量永远指向某个对象,是一个常量指针,而不是指向常量的指针。
final关键字的具体应用
final+变量:
在实际应用中,这种形式是非常少见的。
比如logger是可以的,但是貌似并不是非常实用,或许用户仍然希望通过setter来改变logger变量。
static+final+变量:
常量,经常使用。
final+方法:
JDK中常用,但是自己并未常用。
final+类:
helper类经常使用。
final用于匿名内部类的参数传递:
在多线程测试时,经常使用
final用于方法的参数:
并不常用。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。