java学习(九)static和this使用
static:翻译为静态
-
所有static关键词修饰的都是类相关的,不需要new对象,都是采用类名.的形式访问,不会出现空指针异常
-
static修饰的方法称为静态方法,static修饰的变量称为静态变量
复习变量(引出静态变量)
-
方法体内声明的变量叫局部变量
-
方法体外声明的变量叫成员变量
-
成员变量可以分为静态变量和实例变量,在实例变量前加static关键词就是静态变量了
-
静态代码块
-
静态代码块在类加载时执行,并且只执行一次。 静态代码块实际上是 java 语言为程序员准备的一个特殊的时刻,这个时刻就 是类加载时刻。静态代码块会在main方法之前执行。
静态代码块:
public class StaticTest01{ //静态代码块 static{ System.out.println(111); //先执行 } public static void main(String[] args) { System.out.println("main 执行!"); //最后执行 } //静态代码块 static{ System.out.println(222); //然后执行 } } //静态代码块先执行,然后才是方法执行
-
可以得知:静态代码块是在main方法之前执行的,是因为静态代码块在类加载时执行,并且只执行一次。
访问静态变量和实例变量
public class StaticTest02{ //实例变量 int i = 100; //静态变量 static int j = 111; static{ System.out.println(i); //java:11: 错误: 无法从静态上下文中引用非静态 变量 i System.out.println(j); //编译成功 } public static void main(String[] args){ System.out.println("Hello World!"); } }
静态属性
-
当一个类的某个属性值不会随着对象的改变而变化的时候,建议将该属性定义为静态属性。
-
静态变量在类加载的时候初始化,存储在方法区当中,不需要创建对象,直接通过类名访问
静态方法
-
在实际的开发中,“工具类”当中的方法一般定义为静态方法,因为工具类就是为 了方便大家的使用,将方法定义为静态方法,比较方便调用,不需要创建对象,直接使用类名 就可以访问。
-
当某个动作 在触发的时候需要对象的参与,这个方法应该定义为实例方法
java中的this是什么,内存中存储在哪里,要掌握 this 在实例方法和构造方法中的 用法。
-
this 可以看做一个变量,它是一个“引用”,存储在 Java 虚拟机堆内存的对象内部,this 这个“引用”保存了当前对象的内存地址指向自身,任何一个堆内存的 java 对象都有一个 this 。
-
this 指向“当前对象”,也可以说 this 代表“当前对象”,this 可以使用在实例方法中以及 构造方法中,语法格式分别为“this.”和“this(..)”。this 不能出现在带有 static 的方法当中。
public class ThisInStaticMethod{ public static void main(String[] args) { ThisInStaticMethod.method(); } public static void method(){ System.out.println("method执行"); System.out.println(this); //java:11: 错误: 无法从静态上下文中引用非静态 变量 this } }
得知:this不能出现在 static的方法当中,static 方法执行的过程中是不需要“当前对象”参与的,所以 static 的方法中不能使用 this,因为 this 代表的 就是“当前对象”。
this:this只能在实例方法中使用,谁调用这个实例方法,this就是谁,就是指当前对象!
public class Customer{ private String name; //无参构造方法 public Customer(){ } //有参构造方法 public Customer(String _name){ name = _name; //这里的name就是实例变量neme,_name是接收的局部变量 } //set public void setName(String _name){ name = _name; } //get public String getName(){ return name; } //定义一个实例方法 public void shopping(){ System.out.println(this.name + "is shopping!"); //谁调用就打印谁 System.out.println(name + "is shopping!"); //谁调用就打印谁 } }
调用:
public class CustomerThisTest{ public static void main(String[] args) { CustomerThis jack = new CustomerThis("jack"); jack.shopping(); System.out.println("分界线==============================="); CustomerThis rose = new CustomerThis("rose"); rose.shopping(); } }
得 知 :在实例方法中可以 直接访问当前对象的实例变量,而“this.”是可以省略的。
那么this在什么时候不能省略?
当接收的局部变量参数和实例变量相同的时候,例:name = name;需要写成this.name = name这里的this就不可以省略了哈哈哈哈。【否则name = name这两个name都会被识别成局部变量哦】
-
访问实例变量,实例方法。上面Customer代码块修改:
//定义一个实例方法 public void shopping(){ System.out.println(name + "is shopping!"); //谁调用就打印谁 System.out.println(this.name + "is shopping!"); //谁调用就打印谁 this.pay(); //省略this pay(); } //再定义一个实例方法 public void pay(){ System.out.println(name + "付钱付钱"); } } /* jackis shopping! jackis shopping! jack付钱付钱 jack付钱付钱 分界线=============================== roseis shopping! roseis shopping! rose付钱付钱 rose付钱付钱 */
得出:在一个实例方法当中可以直接去访问其它的实例方法
代码
public class ThisTest { int i = 10; public static void main(String[] args) { //System.out.println(i); //错误: 无法从静态上下文中引用非静态 变量 i。因为main方法有static,i是实例变量,要用引用.去访问 //System.out.println(this.i); // 错误: 无法从静态上下文中引用非静态 变量 this。因为 main 方法带有 static,不能用 this(代表当前对象) ThisTest tt = new ThisTest(); //通过引用访问 System.out.println(tt.i); } }
得知:
-
在 static 的方法中不能直接访问实例变量,须先自己创建一个对象,通过“引用”可以去访问。
-
在 static 的方法中不能通过 this 访问实例变量,因为在 static 方 法中是不能存在 this 的。
同理:
-
main 方法中无法直接调用实例方法 ,因为实例方法也必须要new对象,通过引用调用
this 使用在构造方法中,this(实际参数列表);调用另一个有参的构造方法
-
this();语法要在同一个类中使用
-
this();只能在构造方法第一行,前面不能有其他代码
public class ThisTest02{ public static void main(String[] args){ //调用无参构造 Date d1 = new Date(); d1.detail(); //调用有参构造 Date d2 = new Date(2020,06,19); d2.detail(); } } class Date{ private int year; private int month; private int day; //业务要求,默认创建的日期为 1970 年 1 月 1 日 //无参构造方法 public Date(){ /* this.year = 1970; this.month = 1; this.day = 1; */ //System.out.println("随便写一行代码在this()前"); //错误: 对this的调用必须是构造器中的第一个语句 //无参构造方法调用有参构造方法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 + "日"); } //set和get 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; } }
小总结:
-
代码封装,属性一般都私有化
-
都要有两个构造方法,一个无参构造,一个有参构造。(对象属性的 初始化)
-
都要有对应的set和get方法,这是封装的规定,就算暂时用不到也要写。
-
封装的get方法要指定返回值的类型,不需要传参。
-
封装的set方法不需要返回值,所以返回值类型固定写法void,但是需要传参数。
-
只要调用的方法a和被调用的方法b是在同一个类里面,this.和类名.可以省略
银行存取款代码:其实这3个类写入3个文件内比较好
public class TestCustomerAccount{ public static void main(String[] args){ Account a = new Account("10086",1000,0.0023); Customer c = new Customer("smth",a); //存100 //取960 //取200 c.getAct().deposite(100); c.getAct().withdrow(960); c.getAct().withdrow(2000); } } //客户类 class Customer{ private String name; private Account act; //构造方法 public Customer(){ } //有参构造 public Customer(String name,Account act){ this.name = name; this.act = act; } //set 和 get方法 public void setName(String name){ this.name = name; } public String getName(){ return name; } public void setAct(Account act){ this.act = act; } public Account getAct(){ return act; } } //账号类 class Account{ private String id; private double balance; //余额实例属性 private double annualInterestRate; //年利率实例属性 //无参构造 public Account(){ } //有参构造, public Account(String id, double balance, double annualInterestRate){ //构造方法是创建对象的时候,对象的属性初始化 this.id = id; this.balance = balance; this.annualInterestRate = annualInterestRate; } //各属性set和get,这里是后期查询和修改需要 //为啥每个类都写set和get方法,用不到也要写,因为这是“封装”的规定 public String getId(){ return id; } public void setId(String id){ this.id = id; } public double getBalance(){ return balance; } public void setBalance(double balance){ this.balance = balance; } public double getAnnualInterestRate(){ return annualInterestRate; } public void setAnnualInterestRate(double annualInterestRate){ this.annualInterestRate = annualInterestRate; } //存钱方法 //存钱要传一个参数告诉存多少钱 public void deposite(double money){ //this.balance += money; this.setBalance(this.getBalance() + money); System.out.println("存款成功" + money); } //取钱方法 //取钱需要传一个参数告诉取多少钱 public void withdrow(double money){ if(money > this.getBalance()){ System.out.println("余额不足,取款失败"); return; } this.setBalance(this.getBalance() - money); System.out.println("取款成功"+ money); } }