三大变量的存储区与This关键字

114 阅读7分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第28天,点击查看活动详情

哈喽,大家好!我是Why,一名在读学生,目前刚刚开始进入自己的编程学习生涯。虽然学习起步较晚,但我坚信做了才有0或1的可能。学了一段时间以后也是选择在掘金上分享自己的日常笔记,也希望能够在众多道友的大家庭中打成一片。 本文主要讲解三大变量的存储区与This关键字,如果大家读后觉得有用的话,还请大家多多支持博主:欢迎 ❤️点赞👍、收藏⭐、留言💬 ✨✨✨个人主页:JinHuan

三大变量的存储区

 /*
     栈:方法只要执行,会压栈。(局部变量)
     堆:new出来的对象都在堆中。垃圾回收器主要针对。(实例变量)
     方法区:类的信息,字节码信息,代码片段。(静态变量)
 ​
     方法的代码片段放在方法区,但是方法执行过程当中需要的内存在栈中。
 */
 public class StaticTest07{
     
     // 静态变量在什么时候初始化?类加载时初始化。
     // 静态变量存储在哪里?方法区
     static int i = 100;
 ​
     // 静态代码块什么时候执行?类加载时执行。
     static {
         // 这里可以访问i吗?
         System.out.println("i = " + i);
     }
 ​
     // 实例变量
     int k = 111; // k变量是实例变量,在构造方法执行时内存空间才会开辟。
 ​
     static {
         //k变量可以访问吗?
         // static静态代码块在类加载时执行,并且只执行一次。
         // 类加载时,k变量空间还没有开辟出来呢。
         //错误: 无法从静态上下文中引用非静态 变量 k
         //System.out.println("k = " + k);
 ​
         // 这里可以访问name吗?
         //错误: 非法前向引用
         // 静态代码块和静态变量都在类加载的时候执行,时间相同,只能靠代码的顺序来决定谁先谁后。
         //System.out.println("name = " + name);
     }
 ​
     // 静态变量在静态代码块下面。
     static String name = "zhangsan";
 ​
 ​
     //入口(main方法执行之前实际上执行了很多代码)
     public static void main(String[] args){
         System.out.println("main begin");
         System.out.println("main over");
     }
 }
 ​
 /*
 总结:
     到目前为止,你遇到的所有java程序,有顺序要求的是哪些?
         第一:对于一个方法来说,方法体中的代码是有顺序的,遵循自上而下的顺序执行。
         第二:静态代码块1和静态代码块2是有先后顺序的。
         第三:静态代码块和静态变量是有先后顺序的。
 */

This关键字

 /*
     this:
         1、this是一个关键字,全部小写。
         2、this是什么,在内存方面是怎样的?
             一个对象一个this。
             this是一个变量,是一个引用。this保存当前对象的内存地址,指向自身。
             所以,严格意义上来说,this代表的就是“当前对象”
             this存储在堆内存当中对象的内部。
 ​
         3、this只能使用在实例方法中。谁调用这个实例方法,this就是谁。
         所以this代表的是:当前对象。
 ​
         4、“this.”大部分情况下是可以省略的。
 ​
         5、为什么this不能使用在静态方法中??????
             this代表当前对象,静态方法中不存在当前对象。
 */
 public class ThisTest01{
     public static void main(String[] args){
 ​
         Customer c1 = new Customer("张三");
         c1.shopping();
 ​
         Customer c2 = new Customer("李四");
         c2.shopping();
 ​
         Customer.doSome();
     }
 }
 ​
 // 顾客类
 class Customer{
 ​
     // 属性
     // 实例变量(必须采用“引用.”的方式访问)
     String name;   
 ​
     //构造方法
     public Customer(){
     
     }
     public Customer(String s){
         name = s;
     }
 ​
     // 顾客购物的方法
     // 实例方法
     public void shopping(){
         // 这里的this是谁?this是当前对象。
         // c1调用shopping(),this是c1
         // c2调用shopping(),this是c2
         //System.out.println(this.name + "正在购物!");
 ​
         // this. 是可以省略的。
         // this. 省略的话,还是默认访问“当前对象”的name。
         System.out.println(name + "正在购物!");
     }
 ​
     // 静态方法
     public static void doSome(){
         // this代表的是当前对象,而静态方法的调用不需要对象。矛盾了。
         // 错误: 无法从静态上下文中引用非静态 变量 this
         //System.out.println(this);
     }
 }
 ​
 ​
 class Student{
 ​
     // 实例变量,怎么访问?必须先new对象,通过“引用.”来访问。
     String name = "zhangsan";
 ​
     // 静态方法
     public static void m1(){
         //System.out.println(name);
 ​
         // this代表的是当前对象。
         //System.out.println(this.name);
 ​
         // 除非你这样
         Student s = new Student();
         System.out.println(s.name);
 ​
     }
 ​
     //为什么set和get方法是实例方法?
     public static void setName(String s){
         name = s;
     }
     public String getName(){
         return name;
     }
 ​
     // 又回到上午的问题了?什么时候方法定义为实例方法,什么时候定义为静态方法?
     // 如果方法中直接访问了实例变量,该方法必须是实例方法。
 }
栗子:
 ​
 // 分析:i变量在main方法中能不能访问????
 ​
 public class ThisTest02{
 ​
     // 实例变量
     int i = 100; // 这个i变量是不是必须先new对象才能访问。
 ​
     // 静态变量
     static int k = 111;
 ​
     // 静态方法
     public static void main(String[] args){
         // 错误: 无法从静态上下文中引用非静态 变量 i
         // System.out.println(i);
 ​
         // 怎么样访问i
         ThisTest02 tt = new ThisTest02();
         System.out.println(tt.i);
 ​
         // 静态变量用“类名.”访问。
         System.out.println(ThisTest02.k);
 ​
         // 类名. 能不能省略?
         // 可以
         System.out.println(k);
     }
 }
this的使用
 /*
 1、this可以使用在实例方法中,不能使用在静态方法中。
 2、this关键字大部分情况下可以省略,什么时候不能省略呢?
     在实例方法中,或者构造方法中,为了区分局部变量和实例变量,
     这种情况下:this. 是不能省略的。
 */
 public class ThisTest03{
     public static void main(String[] args){
 ​
         Student s = new Student();
         s.setNo(111);
         s.setName("张三");
         System.out.println("学号:" + s.getNo());
         System.out.println("姓名:" + s.getName());
 ​
         Student s2 = new Student(2222, "李四");
         System.out.println("学号:" + s2.getNo());
         System.out.println("姓名:" + s2.getName());
 ​
     }
 }
 ​
 // 分析一下:以下代码哪里写的不好。
 // 学生类
 class Student{
     //学号
     private int no;
 ​
     //姓名
     private String name;
 ​
     //构造方法无参
     public Student(){
     
     }
 ​
     //构造方法有参
     /*
     public Student(int i, String s){
         no = i;
         name = s;
     }
     */
 ​
     // 上面的构造方法也增强以下可读性
     public Student(int no, String name){
         this.no = no;
         this.name = name;
     }
 ​
     // setter and getter方法
     /*
     public void setNo(int i){
         no = i;
     }
     */
     /*
     public void setNo(int no){ // 就近原则。
         no = no; //这两个no都是局部变量no,和实例变量no没关系。
     }
     */
     public void setNo(int no){ 
         //no是局部变量
         //this.no 是指的实例变量。
         this.no = no; // this. 的作用是:区分局部变量和实例变量。
     }
     public int getNo(){
         return no;
         //return this.no;
     }
     /*
     public void setName(String s){
         name = s;
     }
     */
     /*
     public void setName(String name){ // 就近原则
         name = name; //这两个name都是局部变量name,和实例变量name没关系。
     }
     */
     public void setName(String name){
         this.name = name;
     }
 ​
     /*
     public String getName(){
         return name;
     }
     */
 ​
     public String getName(){ // getName实际上获取的是“当前对象”的名字。
         //return this.name; // 严格来说,这里是有一个 this. 的。只不过这个 this. 是可以省略的。
         return name;
     }
 }
This使用在构造方法中
 /*
     1、this除了可以使用在实例方法中,还可以用在构造方法中。
     2、新语法:通过当前的构造方法去调用另一个本类的构造方法,可以使用以下语法格式:
         this(实际参数列表);
             通过一个构造方法1去调用构造方法2,可以做到代码复用。
             但需要注意的是:“构造方法1”和“构造方法2” 都是在同一个类当中。
 ​
     3、this() 这个语法作用是什么?
         代码复用。
     
     4、死记硬背:
         对于this()的调用只能出现在构造方法的第一行。
 */
 public class ThisTest04{
     public static void main(String[] args){
         // 调用无参数构造方法
         Date d1 = new Date();
         d1.detail();
 ​
         // 调用有参数构造方法
         Date d2 = new Date(2008, 8, 8);
         d2.detail();
     }
 }
 ​
 /*
 需求:
     1、定义一个日期类,可以表示年月日信息。
     2、需求中要求:
         如果调用无参数构造方法,默认创建的日期为:1970年1月1日。
         当然,除了调用无参数构造方法之外,也可以调用有参数的构造方法来创建日期对象。
 */
 class Date{ // 以后写代码都要封装,属性私有化,对外提供setter and getter
     //年
     private int year;
     //月
     private int month;
     //日
     private int day;
 ​
     // 构造方法无参
     // 调用无参数构造方法,初始化的日期是固定值。
     public Date(){
         //错误: 对this的调用必须是构造器中的第一个语句
         //System.out.println(11);
         /*
         this.year = 1970;
         this.month = 1;
         this.day = 1;
         */
         this(1970, 1, 1);
     }
     // 构造方法有参数
     public Date(int year, int month, int day){
         this.year = year;
         this.month = month;
         this.day = day;
     }
 ​
     // 提供一个可以打印日期的方法
     public void detail(){
         //System.out.println(year + "年" + month + "月" + day + "日");
         System.out.println(this.year + "年" + this.month + "月" + this.day + "日");
     }
 ​
     //setter and getter
     public void setYear(int year){
         // 设立关卡(有时间可以设立关卡)
         this.year = year;
     }
     public int getYear(){
         return year;
     }
     public void setMonth(int month){
         // 设立关卡(有时间可以设立关卡)
         this.month = month;
     }
     public int getMonth(){
         return month;
     }
     public void setDay(int day){
         // 设立关卡(有时间可以设立关卡)
         this.day = day;
     }
     public int getDay(){
         return day;
     }
 }