P63 块作用域
在C++中可以在嵌套的块中重新定义一个变量,在内层定义的变量会覆盖外层定义的变量,但在java中不允许这样做
public static void main(String[] args) {
int n = 10;{
int k = 10;/*** 错误提示:Variable 'n' is already defined in the scope* 在C++中可以在嵌套的块中重新定义一个变量,在内层定义的变量会覆盖外层定义的变量,* 但在java中不允许这样做*/int n = 20;}}
P63 & P127 块作用域 & 默认字段初始化
数组会给数组中的元素初始化;类的属性也会在调用构造方法时被初始化;但方法中的局部变量不会被初始化,所以必须明确初始化。
整型初始化为0,浮点型初始化为0.0,String类型初始化为null,boolean类型初始化为false类型
public class Test {
public static void main(String[] args) {
/*** 运行结果:[null, null, null, null, null]* 数组中的元素会被初始化*/String[] arr = new String[5];System.out.println(Arrays.toString(arr));/*** 运行结果:name = null age = 0* 对象中的属性也会被初始化*/Person person = new Person();System.out.println("name = " + person.name);System.out.println("age = " + person.age);/*** 编译出错*/int i;System.out.println(i);}
}class Person{
public String name;public int age;
}
P121 ~ P123 方法参数
java中有2种类型的方法参数
- 基本数据类型(数字、布尔)
- 对象引用
对于基本数据类型,一个方法不可能修改基本数据类型的值,但对于对象引用,方法引用得到的是对象引用的副本,原来的对象引用和副本都引用同一个对象,所以通过副本引用能够修改对象的属性。但是需要注意的是,只能通过副本引用修改对象的值,如果想要通过副本引用修改原来对象引用的值,是不会成功的。
// 程序清单4-4
public class Test {
public static void main(String[] args) {
/*** 方法参数为 基本数据类型* 声明一个变量percent,调用tripleValue()方法* 但由于是按值调用,所以在方法调用完毕后,percent的值仍然为10*/System.out.println("Testing tripleValue:");double percent = 10;System.out.println("Before: percent = " + percent);tripleValue(percent);System.out.println("After: percent = " + percent);/*** 方法参数为 对象引用* 创建一个对象的副本变量,这个副本变量也指向对象本身的地址* 所以当通过副本变量修改对象本身的值时,对象的值发生改变*/System.out.println("\nTesting tripleSalary");var harry = new Employee("Harry", 50000);System.out.println("Before: salary = " + harry.getSalary());tripleSalary(harry);System.out.println("After: salary = " + harry.getSalary());/*** 方法参数为 按值传递* 这里的swap()方法把Alice和Bob变量的地址传递给x和y* 通过x和y能够修改Alice和Bob中变量的值,但是如果在swap()方法中交换两个对象* 那么x存放的是Bob变量,而y存放的是Alice对象* 但在方法结束时,变量Alice和Bob仍然指向原来的对象,并没有发生交换*/System.out.println("\nTesting swap:");var Alice = new Employee("Alice", 70000);var Bob = new Employee("Bob", 60000);System.out.println("Before: Alice = " + Alice.getSalary());System.out.println("Before: Bob = " + Bob.getSalary());tripleSalary(Alice);tripleSalary(Bob);swap(Alice, Bob);System.out.println("After: Alice = " + Alice.getSalary());System.out.println("After: Bob = " + Bob.getSalary());}public static void tripleValue(double x){
x *= 3;}public static void tripleSalary(Employee x){
x.raiseSalary(200);System.out.println("End of method: salary = " + x.getSalary());}public static void swap(Employee x, Employee y){
Employee temp = x;x = y;y = temp;System.out.println("End of method x = " + x.getName());System.out.println("End if method y = " + y.getName());}
}class Employee{
private String name;private double salary;public Employee(String name, double salary){
this.name = name;this.salary = salary;}public String getName() {
return name;}public double getSalary() {
return salary;}public void raiseSalary(double ByPercent){
double raise = salary * ByPercent / 100;salary += raise;}
}
P130 ~ P133 初始化块和静态代码块
初始化代码块的③种方法:
- 在声明中赋值
- 在构造器中设置值
- 在初始化块中赋值
初始化块(构造类时调用):在一个类的声明中,可以包含任意多个代码块。只要构造这个类的对象,这些块就会被执行。但是,通常会将初始化块放在构造器中。
静态代码块(加载类时调用):随着类的加载而执行,而且只执行一次。也就是说这些代码不需要实例化类就能够被调用。一般情况下,如果有些代码必须在项目启动的时候就执行,就需要使用静态代码块。
import java.util.Random;public class Test {
public static void main(String[] args) {
var staff = new Employee[3];staff[0] = new Employee("Harry", 40000);staff[1] = new Employee(60000);staff[2] = new Employee();for (Employee e : staff){
System.out.println(e);}}
}class Employee{
private static int nextId;private int id;private String name = "";private double salary;// 静态代码块:用于初始化静态变量static{
var generator = new Random();nextId = generator.nextInt(10000);}// 初始化块{
id = nextId;nextId++;}public Employee() {
}public Employee(String name, double salary) {
this.name = name;this.salary = salary;}public Employee(double salary){
this("Employee #" + nextId, salary);}public int getId() {
return id;}public String getName() {
return name;}public double getSalary() {
return salary;}@Overridepublic String toString() {
return "Employee{" +"id=" + id +", name='" + name + '\'' +", salary=" + salary +'}';}
}