java基础(五)this关键字、final关键字、值传递

        本文主要讲述java基础中的this关键字和final关键字的定义以及其用法,还通过例题详细介绍了java的值传递机制。

一、this关键字

        1、什么是this关键字

                this关键字代表当前对象

        2、为什么使用this关键字

                有时不方便直接使用对象,需要用this关键字来代替

        3、如何用this关键字

(1)this.属性

        this.属性一般表示在类当中调用全局变量

 程序代码 :
public class Student {
   public String name;
   public void run(String aaaa){
       this.name=aaaa;
   }
}
public class Test {
    public static void main(String[] args) {
    Student student= new Student();
    ce.run("aaaa");
    Student student1= new Student();
    ce.run("hhhh");
    }
}
代码分析:
①程序堆栈运行图如下

②为什么设置对象名称student和student1

        原因:需要区分你调用的是哪个run方法,所以添加一个对象名称

③this.name调用的是全局变量为什么不是局部变量。

        原因:因为全局变量属于当前对象,而局部变量不属于全局变量。

(2)this.方法名

①代码:调用没有static关键字的方法
例:
public class Student {
   public String name;
   public void run(String name){
       this.name=name;
   }
   public void aaa(){
       this.run("aaaa")   
   }
}
②代码:调用有static关键字的方法
注意:

        此代码中run方法被static修饰,他就不能在调用this代码,应该去掉,报错图在代码下

原因:

        ①static修饰的代码被所有对象共享,所以this可以调用static修饰的方法

        ②static修饰的方法当中不能出现this关键字,因为类是构建对象的模板,有类不一定有对象

例:
public class Student {
   public String name;
   public static void run(String name){
       /*this.name=name;该语句删掉,static修饰的方法当中不能出现this关键字*/
   }
   public void aaa(){
       this.run("aaaa")   
   }
}

(3)this() //了解就行,this的用法主要体现在 this.属性和this.方法名。

        this()表示访问构造器,指的是构造器的调用,

注意:
        ①this()不能再普通方法中使用,只能在构造方法中使用

        示例代码如下:

public class Student {
   public String name;
   public Student(){
          
   }
    public Student(String name){
       this()  ; 
   }
}
②this()在构造方法中使用的必须是第一条语句
③在一个类下两个构造方法中不能通过this()相互调用

示例代码如下:

public class Student {
   public String name;
   public Student(){
       this("nnnn")/*此时该处会发生报错*/
   }
    public Student(String name){
       this()  ; 
   }
}
④不能与super()同时使用

二、final关键字

        final关键可以修饰变量、方法和类。

1、final修饰类

        final所修饰的类不能被继承

示例代码如下:
public final class A{
    
}
public class B extends A{
   /* 注意此时会报错,final修饰的类不能被继承*/
}

2、final修饰方法

        final修饰的方法不能被重写

示例代码如下:
public class Student {
   public String name;
   public void final run(){
       System.out.pritnln("aaa");
   }
}
public class Test extends Student {
    /* 此处会报错,final修饰的方法不能被重写*/
   public void run(){
      System.out.pritnln("bbb");
   }
}

3、final修饰变量

        final所修饰的变量叫做常量,常量是只能被赋值一次的变量,常量的变量名必须大写。

(1)final修饰全局变量和局部变量

        ①final修饰全局变量

        全局变量:在类里边所定义的变量

        fianl修饰全局变量需要赋值,否则会报错。

        示例代码如下:
        未赋初始值:

     赋初始值:

        原因:final所修饰的变量叫做常量,常量只能被赋值一次,而全局变量具有默认值(根据数据类型),所以需要赋初始值。
        补充:数据默认值

                引用数据类型:默认值为null

                整形:默认值为0

                浮点型:默认值为0.0

                布尔型:默认值为flase

                char类型:默认值为空

②final修饰局部变量

          局部变量:在方法里边定义的变量

         fianl修饰局部变量不需要赋值,但如果要使用则必须赋值,否则会报错。但局部变量如果不被final修饰,在使用时也需要赋初始值。所以加不加final对局部变量影响不大

示例代码如下:

(2)final修饰基本数据类型所定义的变量和引用数据类型所定义的变量

        ①final修饰基本数据类型所定义的变量

        fianl修饰的基本数据类型,其值不能被改变

        原因:对于基本数据类型而言,final固定的是其对象的值,不能被改变(对于基本数据类型来说对象存储的是他本身的值例如int a=10,存储的是10,而被final修饰后10就不能被改变了,所以在修改时会发生报错),详细流程图如下可对照引用数据类型观看
示例代码如下:
例:基本数据类型 没有被final修饰
public class Student {
   public String name;
   int a=10;
   public void run(){
       a=11;
   }
}
例:基本数据类型 被final修饰
public class Student {
   public String name;
  final int A=10;
   public void run(){
      A=11;/*此时这里会发生报错*/
   }
}
流程图:

②final修饰引用数据类型所定义的变量
        引用数据类型:

         引用数据类型包括:类、数组、接口

        对于引用数据类型而言,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、示例1:

(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);
        }
}

(2)输出结果如下:

        name--->李四

        name--->张三

(3)流程如下

        画堆栈流程图,第一步main方法入栈,然后定义一个nameString字符串其值为"张三"的存储地址0x1,"张三"存储在方法区的字符串常量池中,其地址为0x1。

        第二步调用name(nameString)方法入栈,该方法中有一个String类型的局部变量name,其值为nameString字符串的值即0x1(主要java只有值传递),然后方法继续进行 name="李四",此时在字符串常量池中先存储"李四"其地址为0x2,再把0x2赋值给name(记住java是值传递,只传送变量的值,不传送变量其本身,所以nameString并不会发生改变)。最后输出,输出的是name--->李四。

        第三步输出完之后name(nameString)方法出栈,回到main方法中,在执行输出,输出的是name--->张三。

2、示例2:

(1)示例代码如下

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());
    }
}

(2)输出结果如下

        张三 18

        李四 20

(3)流程如下

        画出堆栈流程图,第一步main方法入栈,创建person对象地址为0x1,该对象包含(nameString=0x2,age=18,toString(),name(),)方法区存储张三的地址值为0x2,调用toString方法,输出张三 18。

        第二步,name方法入栈,name方法中有一个局部变量person,同时对他进行了值传递,person的值为0x1,同时namestring的值被改为李四的地址值0x3,age改为20,改完之后person置空,出栈,然后进行toSting方法的调用,注意此时0x1中的内容已经被修改,输出李四 20。

3、示例3:

(1)示例代码如下

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());
    }
}

(2)输出结果如下

        张三 18

        李四 20

(3)流程如下(流程图为了方便画图,直接把字符串写在对象内了,应该在字符串常量池,change()方法也没写。)

        画出堆栈流程图,main方法入栈,创建zhansa值为0x1(name =0x3 、age=18、),和lisi对象值为0x2(name =0x4 、age=20、),张三0x3和李四0x4都存储在字符串常量池中。

        调用change方法,注意change方法被static修饰存储在方法区中,创建一个Student类型的 对象temp值为0x5(name =0x6 、age=20、)王五0x6存储在字符串常量池中和对象s1值为0x1和对象s2值为0x2。接着将s1即0x1传给temp,再将s2的值即0x2传给s1,最后将temp值即0x1传给s2。

        然后出栈,注意上述修改并没有对zhangsan和对象lisi所指向的地址造成影响,输出为张三 18 李四 20。

4、示例4:

(1)示例代码如下

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;
    }
}

(2)输出结果如下

        0

        42 42

(3)流程如下

        画堆栈内存图,main方法入栈,创建 student对象0x1(start()、fix()),调用start()方法,创建一个two对象0x2(byte x),此时没有赋值,默认值为0。然后进行输出0。

        然后生成一个two2对象,他指向的值由fix方法决定,fix()方法入栈将0x2的地址赋值给tt,然后将0x2中x的值改为42,返回tt即0x2,所以two2的值为0x2,此时输出42 42。

  • 12
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值