目录
解析 this 关键字
this 关键字定义
this 关键字代表当前对象的引用。它用于在对象的方法或构造器中引用当前对象。
什么时候使用 this 关键字
使用 this 关键字的原因是有时候我们需要区分局部变量和实例变量(类的成员变量),或者需要在类内部明确引用当前对象时。
怎样使用 this 关键字
this.属性 通常用于在类的方法中调用实例变量,尤其当方法参数的名字和实例变量的名字相同时。
public class Student {
public String name;
public void setName(String aaaa) {
this.name = aaaa;
}
}
public class Test {
public static void main(String[] args) {
Student student = new Student();
student.setName("aaaa");
Student student1 = new Student();
student1.setName("hhhh");
}
}
设置对象名称 student 和 student1 是为了区分两个不同的对象,分别调用各自的 setName 方法。
this.name 指代的是当前对象的实例变量,而非方法中的局部变量。
this.方法名调用没有 static 关键字修饰的方法时,可以使用 this 来显式地调用该方法。
public class Student {
public String name;
public void setName(String name) {
this.name = name; // 使用 this 调用非静态方法
}
public void initialize() {
this.setName("aaaa"); // 使用 this 调用 setName 方法
}
}
在 static 方法中不能使用 this 关键字,因为 static 方法是属于类而不是某个对象的。
public class Student {
public String name;
public static void run(String name) {
// this.name = name; // 错误:不能在 static 方法中使用 this
}
public void aaa() {
// this.setName("aaaa"); // 错误:static 方法不能通过 this 调用
}
}
static 修饰的方法和变量是属于类的,不属于某个对象,所以 this 不能用于 static 方法。
static 方法中没有 this 关键字的上下文,因为它们不依赖于任何对象。
this() 用于调用类的构造方法,只能在构造器中使用,且必须是构造器中的第一条语句。
public class Student {
public String name;
public Student() {
// 默认构造方法
}
public Student(String name) {
this(); // 调用无参数的构造方法
}
}
在一个类中,两个构造方法不能通过 this() 互相调用,否则会引起编译错误。
this() 和 super() 不能同时出现在同一个构造方法中。
解析 final 关键字
final 修饰类
public final class A {
// 这是一个不能被继承的类
}
public class B extends A { // 错误:无法继承被 final 修饰的类
}
final 修饰方法
public class Student {
public String name;
public final void run() {
System.out.println("aaa");
}
}
public class Test extends Student {
@Override
public void run() { // 错误:无法重写被 final 修饰的方法
System.out.println("bbb");
}
}
final 修饰变量
final 修饰的变量成为常量,常量只能被赋值一次,且在类中使用时,必须在声明时初始化。
final 修饰的全局变量(类的成员变量)必须被赋初始值,否则会报错。局部变量(方法内的变量)不需要赋值,但如果要使用则必须赋值。
局部变量是在方法内部定义的变量。final 修饰的局部变量不需要在定义时立即赋值,但必须在使用之前进行赋值,否则会报错。
无论局部变量是否被 final 修饰,在使用时都需要初始化。所以,final 对局部变量的影响不大。
final 修饰基本数据类型和引用数据类型的变量
原因:对于基本数据类型,final 固定的是变量的值。比如:
public class Student {
public String name;
int a=10;
public void run(){
a=11;
}
}
publicclass Student {
public String name;
final int A=10;
public void run(){
A=11;/*此时这里会发生报错*/
}
基本数据类型的变量在内存中存储的是其值本身,例如 int a = 10,存储的是值 10。
一旦用 final 修饰,值就不能改变,尝试改变时会发生编译错误。
引用数据类型包括类、数组、接口等。final 修饰的引用数据类型变量,固定的是对象的引用地址,变量无法改变其指向的对象,但对象的内容可以改变。
public class Student {
int[]arr1 = new int[]{1,2,3};
int[]brr = new int[]{4,5,6};
public void change(){
arr1=brr;
}
public void change1(){
arr1[2]=10;
}
}
被 final 修饰后,该引用地址不能改变,但对象内容可以改变。比如可以修改数组的元素,但不能让该变量指向新的数组对象。
public class Student {
int[]ARR1 = new int[]{1,2,3};
int[]BRR = new int[]{4,5,6};
public void change(){
ARR1=BRR;/*此时,该处代码会发生报错*/
}
public void change1(){
ARR1[2]=10;
}
}
Java 的值传递
Java 中只有值传递(传递变量的副本),而没有引用传递。以下通过一些示例代码来进一步理解。
示例 1:
public class A {
public static void main(String[] args) {
String nameString = "张三";
name(nameString);
System.out.println("main--- > " + nameString);
}
public static void name(String name) {
name = "李四";
System.out.println("name---> " + name);
}
}
name---> 李四
main--- > 张三
定义了一个字符串变量 nameString,其值为 "张三"。
"张三" 存储在字符串常量池中,其地址为 0x1。nameString 保存的是这个地址(0x1)。
name(nameString) 方法被调用,将 nameString 的值(0x1)作为参数传入。
方法中定义了一个局部变量 name,其值为 nameString 的值(即 0x1)。
在方法体内,name = "李四" 这一行代码执行,字符串常量池中添加 "李四",其地址为 0x2。
将 0x2 赋值给 name,此时 name 的值为 0x2。
输出 nameString,打印结果为 "张三",因为 nameString 仍然指向 0x1(未被修改)。
示例 2:
public class Person {
private String nameString;
private int age;
public Person (String nameString,int age){
this.age=age;
this.nameString=nameString;
}
@Override
public String toString(){
return "Person [nameString="+ nameString +",age="+age+"]";
}
public static void name(Person person){
person.age=20;
person.nameString="李四";
person=null;
}
public static void main(String[] args) {
Person person =new person("张三",18);
System.out.println(person.toString());
name(person);
System.out.println(person.toString());
}
}
Person [nameString=张三, age=18]
Person [nameString=李四, age=20]
在方法 modifyPerson 中,person 的引用被修改,但这不影响传入的原始对象。因此,尽管 person 参数被设置为 null,但在 main 方法中,person 对象仍然存在且已被修改。
示例 3:
public class Student {
private String name;
private int age;
public Student(String name,int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + "]";
}
public static void change(Student s1, Student s2){
Student temp = new Student( name: "王五", age: 20);
temp = s1;
s1 = s2;
s2 = temp;
}
public static void main(String[] args) {
Student zhangsan = new Student( name: "张三", age: 18);
Student lisi = new Student( name: "李四", age: 20);
Student.change(zhangsan, lisi);
System.out.println(zhangsan.toString());
System.out.println(lisi.toString());
}
}
Student [name=张三, age=18]
Student [name=李四, age=20]
在方法 change 中,交换的是 s1 和 s2 的引用,而非对象本身。main 方法中的 zhangsan 和 lisi 仍然指向原来的对象,因此输出未发生变化。
示例 4:
class Two{
byte x;
}
public class Student {
public static void main(String[] args){
Student student = new Student();
student.start(;
}
void start( {
Two two = new Two();
System.out.print(two.x +" ");Two two2 = fix(two);
System.out.println(two.x + " "+two2.x);
}
Two fix(Two tt) {
tt.x =42;return tt;
}
}
0
42 42
总结
this 关键字用于引用当前对象的实例变量或方法,通常在需要区分局部变量和实例变量时使用。
final 关键字用于定义不能更改的类、方法和变量。在使用 final 修饰变量时需要小心,特别是在对象引用和基本数据类型之间的差异。
Java 中的参数传递是值传递,意味着方法操作的是传递的变量副本,而不是变量本身。这一点在理解 Java 的内存管理和对象操作时非常重要。