JavaSE基础篇 | static关键字和this关键字

追求适度,才能走向成功;人在顶峰,迈步就是下坡;身在低谷,抬足既是登高;弦,绷得太紧会断;人,思虑过度会疯;水至清无鱼,人至真无友,山至高无树;适度,不是中庸,而是一种明智的生活态度。

导读:本篇文章讲解 JavaSE基础篇 | static关键字和this关键字,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

目录

🏀static关键字

🥅static关键字理解

🥅什么时候使用static关键字

🥅空引用访问静态不会空指针

🥅关于实例方法的调用

🥅静态代码块

🥅实例代码块

🏀this关键字 

🥅this的内存结构

🥅this什么时候不能省

🥅this()的用法

🥅小试牛刀

🏀总结


🏀static关键字

🥅static关键字理解

  ❤️static:
        1、static翻译为“静态”
        2、所有static关键字修饰的都是类相关的,类级别的
        3、所有static修饰的,都是采用“类名.”的方式访问
        4、static修饰的变量:静态变量
        5、static修饰的方法:静态方法   
  ❤️ 变量的分类:
       ⭐️变量根据声明的位置进行划分:
          (1)在方法体当中声明的变量叫做:局部变量。
          (2)在方法体外(类体中)声明的变量叫做:成员变量。
     
      ⭐️成员变量又可以分为:
            实例变量、静态变量

class VarTest{
//1. 以下实例的,都是对象相关的,访问时采用“引用.”的方式访问。需要先new对象。
	// 实例相关的,必须先有对象,才能访问,可能会出现空指针异常。
	int i;	// 成员变量中的实例变量
	public void m2(){ // 实例方法
		// 局部变量
		int x = 200;
	}


//2. 以下静态的,都是类相关的,访问时采用“类名.”的方式访问。不需要new对象。
	// 不需要对象的参与即可访问,没有空指针异常的发生。
	static int k;// 成员变量中的静态变量
	// 静态方法
	public static void m1(){
        // 局部变量	
		int m = 100;
	}
	
}

🥅什么时候使用static关键字

❤️什么时候变量声明为实例的,什么时候声明为静态的?
    ⭐️如果这个类型的所有对象的某个属性值都是一样的,不建议定义为实例变量,浪费内存空间。建议定义为类级别特征,定义为静态变量在方法区中只保留一份,节省内存开销!
    ⭐️一个对象一份的是实例变量!
    ⭐️所有对象一份的是静态变量!

❤️例1:不使用static

public class StaticTest02{
	public static void main(String[] args){
//1.创建一个c1对象
		Chinese c1 = new Chinese("1231456456456456","张三","中国");
		System.out.println(c1.idCard);
		System.out.println(c1.name);
		System.out.println(c1.country);
//2.创建一个c2对象
		Chinese c2 = new Chinese("7897897896748564","李四","中国");
		System.out.println(c2.idCard);
		System.out.println(c2.name);
		System.out.println(c2.country);
	}
}

//3. 定义一个类:中国人
class Chinese{
	// 每一个人的身份证号不同,所以身份证号应该是实例变量,一个对象一份。
	String idCard; 
	// 姓名也是一个人一个姓名,姓名也应该是实例变量。
	String name;

	// 对于“中国人”这个类来说,国籍都是“中国”,不会随着对象的改变而改变。
	// 显然国籍并不是对象级别的特征。
	// 国籍属于整个类的特征。整个族的特征。
	// 假设声明为实例变量,内存图是怎样的?
	// 假设声明为静态变量,内存图又是怎样的?
	String country;

// 无参数构造方法
	public Chinese(){
	
	}
// 有参数构造方法
	public Chinese(String s1,String s2, String s3){
		idCard = s1;
		name = s2;
		country = s3;
	}
}

⭐️内存图

JavaSE基础篇 | static关键字和this关键字

❤️例2:使用static

 ⭐️加static的变量叫做静态变量
      (1)静态变量在类加载时初始化,不需要new对象,静态变量的空间就开出来了。
      (2)静态变量存储在方法区

 ⭐️不加static的变量叫做实例变量
      (1)实例变量在new创建对象,实例变量的空间就开出来了。
      (2)实例变量存储在堆区

⭐️注意:

实例变量在堆区,创建对象时(new对象、或者说是构造方法执行时)完成初始化!

静态变量在方法区,在类加载时初始化!

public class StaticTest02{
	public static void main(String[] args){
		// 访问中国人的国籍
		// 静态变量应该使用类名.的方式访问
		System.out.println(Chinese.country);

		Chinese c1 = new Chinese("1231456456456456","张三");
		System.out.println(c1.idCard);
		System.out.println(c1.name);

		Chinese c2 = new Chinese("7897897896748564","李四");
		System.out.println(c2.idCard);
		System.out.println(c2.name);

		// idCard是实例变量,必须先new对象,通过“引用.” 访问
		// 错误: 无法从静态上下文中引用非静态 变量 idCard
		//System.out.println(Chinese.idCard);
	}
}

// 定义一个类:中国人
class Chinese{
    // 每一个人的身份证号不同,所以身份证号应该是实例变量,一个对象一份。
	String idCard; 
    // 姓名也是一个人一个姓名,姓名也应该是实例变量。
	String name;
    // 重点重点五颗星:加static的变量叫做静态变量
	// 静态变量在类加载时初始化,不需要new对象,静态变量的空间就开出来了。
	// 静态变量存储在方法区。
	static String country = "中国";//当时就进行赋值初始化

	// 无参数
	public Chinese(){
	
	}

	// 有参数
	public Chinese(String s1,String s2){
		idCard = s1;
		name = s2;
	}
}


⭐️内存图

java中一共有三大变量:

(1)静态变量:定义在类体中,用static修饰,属于类级别的;存储在方法区

(2)实例变量:定义在类体中,不用static修饰,属于对象级别的;存储在堆区

(3)局部变量:定义在方法体中,存储在栈区

JavaSE基础篇 | static关键字和this关键字

🥅空引用访问静态不会空指针

  ⭐️实例的:一定需要使用“引用.”来访问。

  ⭐️静态的:建议使用“类名.”来访问,但使用“引用.”也行(不建议使用”引用.”)。    
  ⭐️结论:空指针异常只有在“空引用”访问“实例”相关的,都会出现空指针异常。使用“引用.”访问“静态”不会出现空指针异常。

public class StaticTest03{
	public static void main(String[] args){
//1. 通过"类名."的方式访问静态变量
		System.out.println(Chinese.country);
		// 创建对象
		Chinese c1 = new Chinese("1111111", "张三");
		System.out.println(c1.idCard); // 1111111
		System.out.println(c1.name); // 张三
//2. 通过"引用."的方式访问静态变量也是可以的
		System.out.println(c1.country); // 中国

//3. c1是空引用,访问实例变量会空指针异常!访问静态变量不会空指针异常!
		c1 = null;
		//访问静态变量不会出现空指针异常。
		// 因为静态变量不需要对象的存在。
		// 实际上以下的代码在运行的时候,还是:System.out.println(Chinese.country);
		System.out.println(c1.country);// 实际上运行时会把c1替换成Chinese

//4. 这个会出现空指针异常,因为name是实例变量。
		System.out.println(c1.name);
	}
}

class Chinese{

	// 实例变量
	String idCard;
	String name;

	// 静态变量
	static String country = "中国";

	//构造方法
	public Chinese(String x, String y){
		idCard = x;
		name = y;
	}
}

🥅关于实例方法的调用

⭐️static修饰的统一都是静态的,都是类相关的,不需要new对象;直接采用“类名.”访问。
⭐️当一个属性是对象级别的,所有对象的这个属性的值是一样的,建议定义为实例变量!

 ❤️例1

public class StaticTest04{
	public static void main(String[] args){

//1. 对于静态变量:这是比较正规的方式,静态方法采用“类名.”
		StaticTest04.doSome();

//2. 对于实例变量,先new对象;用“引用.”访问
		StaticTest04 st = new StaticTest04();
		st.doSome();

//3. 空引用
		st = null;
		// 对于静态变量,不会出现空指针异常
		st.doSome(); // 这个代码在最终执行的时候还是会转变为:StaticTest04.doSome();

		// 实例方法doOther()
		// 对象级别的方法(先new对象,通过“引用.”来访问)
		// 错误: 无法从静态上下文中引用非静态 方法 doOther()
		StaticTest04.doOther();

		StaticTest04 st2 = new StaticTest04();
		st2.doOther();

		// 空引用
		st2 = null;
		// 空引用调用实例方法会出现什么问题?空指针异常。
		//st2.doOther();

	}

//1. 静态方法(静态方法不需要new对象,直接使用“类名.”来访问)
	// 但是也可以使用“引用.”来访问,不建议用。(因为其他程序员会感到困惑)
	public static void doSome(){
		System.out.println("静态方法doSome()执行了!");
	}

//2. 实例方法(实例相关的都需要new对象,使用"引用."来访问。)
	public void doOther(){
		System.out.println("实例方法doOther执行了!");
	}
}

⭐️总结:

从第一天开始讲解HelloWorld到目前为止,一个类当中一共就写过这些东西。
类{
            实例相关的都是需要new对象的,通过”引用.”访问。
            ①实例变量;
            ②实例方法;

            静态相关的都是采用“类名.”访问。也可以使用“引用.”,只不过不建议。
            ①静态变量;
            ②静态方法;
}

❤️例2

⭐️关于方法来说,什么时候定义为实例方法?什么时候定义为静态方法?
参考标准:当这个方法体当中,直接访问了实例变量,这个方法一定是实例方法。此方法一般都是描述了一个行为,如果说该行为必须由对象去触发;那么该方法定义为实例方法。

⭐️我们以后开发中,大部分情况下,如果是工具类的话,工具类当中的方法一般都是静态的。(静态方法有一个优点,是不需要new对象,直接采用类名调用,极其方便。工具类就是为了方便,所以工具类中的方法一般都是static的)

⭐️类 = 属性 + 方法
    (1)属性描述的是:状态
    (2)方法描述的是:行为动作
⭐️一个方法代表了一个动作,什么时候方法定义为实例方法?

例如:张三考试,得分90,李四考试,得分100;不同的对象参加考试的结果不同。我们可以认定“考试”这个行为是与对象相关的行为;建议将“考试”这个方法定义为实例方法。

public class StaticTest05{
	public static void main(String[] args){
//1.getID是实例方法,必须先new对象		
        User u = new User();
		System.out.println(u.getId()); //0
//2.名字name是实例变量,必须先new对象	
		User x = new User();
		x.printName1();

	}
}


//实例变量访问的语法机制是什么?
//语法:引用.实例变量名
class User{

	// 实例变量,需要对象
	private int id;

	// 实例变量
	private String name; // 首先先分析的是,这个name是对象级别的,一个对象一份。


	// 打印用户的名字这样的一个方法。
	public void printName1(){ 
		System.out.println(name);
	}

	public void setId(int i){// 不能加static,加static就和对象没关系了
		id = i; //id是实例变量,上面必须是实例方法才行
	}
	public int getId(){// 不能加static
		return id;
	}
}

🥅静态代码块

  ⭐️使用static关键字可以定义:静态代码块
  ⭐️什么是静态代码块,语法是什么?

 static {
            java语句;
            java语句;
        }

 ⭐️static静态代码块在什么时候执行呢?
静态代码块有这样的特征/特点:类加载时执行,并且只执行一次

 ⭐️注意:静态代码块在类加载时执行,并且在main方法执行之前执行。

 ⭐️静态代码块一般是按照自上而下的顺序执行。 

 ⭐️静态代码块有什么用?
        第一:静态代码块不是那么常用。(不是每一个类当中都要写的东西。)
        第二:静态代码块这种语法机制实际上是SUN公司给我们java程序员的一个特殊的时刻/时机;这个时机叫做:类加载时机
        第三:具体的业务:我们编写的程序中,只要是类加载了,请记录一下类加载的日志信息(在哪年哪月哪日几时几分几秒,哪个类加载到JVM当中了)。
       第四:思考这些记录日志的代码写到哪里呢? 写到静态代码块当中。

 ❤️例1

public class StaticTest06{
//1. 静态代码块(特殊的时机:类加载时机。)
	static {
		System.out.println("A");
	}
//2. 一个类当中可以编写多个静态代码块
	static {
		System.out.println("B");
	}
//3. 程序入口
	public static void main(String[] args){
		System.out.println("Hello World!");
	}
//4. main方法后再编写一个静态代码块
	static{
		System.out.println("C");
	}
}
//5. 执行结果
A
B
C
Hello World!

 ❤️例2

栈:方法只要执行,会压栈。(局部变量)
堆:new出来的对象都在堆中,垃圾回收器主要针对堆中的数据。(实例变量)
方法区:类的信息,字节码信息,代码片段。(静态变量)
总结:方法的代码片段放在方法区,但是方法执行过程当中需要的内存在栈中。

注意:静态代码块可以访问静态变量;静态代码块和静态变量都在类加载的时候执行,时间相同,只能靠代码的顺序来决定谁先谁后。

public class StaticTest07{
	
//1. 静态变量在什么时候初始化?类加载时初始化。
	// 静态变量存储在哪里?方法区
	static int i = 100;

//2. 静态代码块什么时候执行?类加载时执行。
	//只要是代码一定存放在代码区
	//--------------静态代码块可以访问静态变量!
	static {
		System.out.println("i = " + i);		// 这里可以访问i
	}

	// ----------------实例变量
	int k = 111; // k变量是实例变量,在new构造方法执行时内存空间才会开辟。
	static {
		// static静态代码块在类加载时执行,并且只执行一次。
		// 类加载时,k变量空间还没有开辟出来呢。
		//错误: 无法从静态上下文中引用非静态 变量 k
		System.out.println("k = " + k);	
	}
//3.
     static{
        //------------------这里可以访问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是有先后顺序的。
        第三:静态代码块和静态变量是有先后顺序的。

🥅实例代码块

  ⭐️除了静态代码块之外,还有一种语句块叫做:实例语句块
  ⭐️实例语句语法?

   {
        java语句;
        java语句;
        java语句;
    }

 ⭐️实例语句块在什么时候执行?
只要是构造方法执行,必然在构造方法执行之前,自动执行“实例语句块”中的代码;并且每次都会执行。实际上这也是SUN公司为java程序员准备一个特殊的时机,叫做对象构建时机
 ⭐️几个方法有相同的代码,就可以把他们提取出来放到实列语句块里!减少代码冗余

❤️例1

public class InstanceCode{

    //入口
    public static void main(String[] args){
        System.out.println("main begin");
        new InstanceCode();
        new InstanceCode();

        new InstanceCode("abc");
        new InstanceCode("xyz");
    }


    //实例语句块
    {
        System.out.println("实例语句块执行!");    
    }

    // Constructor
    public InstanceCode(){
        System.out.println("无参数构造方法");
    }

    // Constructor
    public InstanceCode(String name){
        System.out.println("有参数的构造方法");
    }

}
//执行结果
main begin
实例语句块执行!
无参数构造方法
实例语句块执行!
无参数构造方法
实例语句块执行!
有参数的构造方法
实例语句块执行!
有参数的构造方法

❤️例2:判断代码执行的顺序(重要)

静态代码块和实例语句块的区别:

(1)static静态代码块在类加载时执行,并且只执行一次;是一个类加载时机,在main方法之前执行;常用来记录一下类加载的日志信息。

(2)实例语句块只要是构造方法执行,在构造方法之前执行,每次都会执行;是一个对象构建时机;常用来提取几个方法中的相同代码放到实例语句块当中,用来减少代码的冗余想·

public class CodeOrder{	
//1. 静态代码块
	static{
		System.out.println("A");
	}
//2. 程序入口
	// A X Y C B Z
	public static void main(String[] args){
		System.out.println("Y");
		new CodeOrder();
		System.out.println("Z");
	}
//3. 构造方法
	public CodeOrder(){
		System.out.println("B");
	}
//4. 实例语句块
	{
		System.out.println("C");
	}
//5. 静态代码块
	static {
		System.out.println("X");
	}

}

总结执行顺序:静态代码块—》main方法入口—》实列语句块—》new对象(构造方法)

🏀this关键字 

🥅this的内存结构

⭐️this是一个关键字,全部小写。
⭐️this是什么,在内存方面是怎样的?
    (1) 一个对象一个this
    (2)this是一个变量,是一个引用。this保存当前对象的内存地址,指向自身。
    (3)严格意义上来说,this代表的就是“当前对象”this存储在堆内存当中对象的内部

⭐️this只能使用在实例方法中。谁调用这个实例方法,this就是谁。
     所以this代表的是:当前对象。

⭐️“this.”大部分情况下是可以省略的。

⭐️为什么this不能使用在静态方法(static)中?
      this代表当前对象,静态方法中不存在当前对象。

❤️例1

public class ThisTest01{
	public static void main(String[] args){
//创建一个对象,并初始化为"张三"
		Customer c1 = new Customer("张三");
		c1.shopping();
//创建另一个对象,并初始化为"李四"
		Customer c2 = new Customer("李四");
		c2.shopping();
        //static静态方法用类名调用,不需要this
		Customer.doSome();
	}
}

// 顾客类
class Customer{
//1. 属性
	// 实例变量(必须采用“引用.”的方式访问)
	String name;   

   // 构造方法,用来创建对象和给变量初始化的
	public Customer(){ //无参构造方法
	
	}
	public Customer(String s){ //有参构造方法
		name = s;
	}

//3. 顾客购物的方法
	// 实例方法
	public void shopping(){
		// 这里的this是谁?this是当前对象。
		// c1调用shopping(),this是c1
		// c2调用shopping(),this是c2
		System.out.println(this.name + "正在购物!");

		// this. 是可以省略的。
		// this. 省略的话,还是默认访问“当前对象”的name。
		//实例变量我们必须用“引用.”来访问;这里实际上省略了this.
		System.out.println(name + "正在购物!");
	}

//3. 静态方法
	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 void setName(String s){
		name = s;
	}
	public String getName(){
		return name;//省略了this.实际上是this.name
	}

	// 又回到上午的问题了?什么时候方法定义为实例方法,什么时候定义为静态方法?
	// 如果方法中直接访问了实例变量,该方法必须是实例方法。
}

⭐️内存图

JavaSE基础篇 | static关键字和this关键字

❤️例2

public class ThisTest02{
//1. 实例变量,必须先new对象才能访问,采用“引用.”
	int i = 100; 
//2. 静态变量,使用"类名."就可以访问;且类名可以省略
	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可以使用在实例方法中,不能使用在静态方法中。
⭐️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;
	} 
/*   
    //为了增强可读性,进行修改;但是此时又会出现问题
    //根据就近原则,下面的no和name都是局部变量,和实例变量没关系!
    public Student(int no, String name){ //都是这里的no和name
		no = no;
		name = name;
	} 
*/
	// 再次更改上面的构造方法也增强以下可读性
	public Student(int no, String name){
		this.no = no;
		this.name = name; //此时加上this.就可以区分局部变量和实例变量!且不能省略!
	}

// setter and getter方法---------也可以进行更改
	public void setNo(int i){
		no = i;
	}
	public int getNo(){
		return no; // 这里也有this.但是可以省略!this.no当前对象的no!
        //return this.no;
	}
	public void setName(String name){
		this.name = name;
	}
	public String getName(){
		return name;
	}

	}
}

🥅this()的用法

⭐️this除了可以使用在实例方法中,还可以用在构造方法(无参构造调用有参构造)中。
⭐️新语法:通过当前的构造方法去调用另一个本类的构造方法,可以使用以下语法格式:
this(实际参数列表);通过一个构造方法1去调用构造方法2,可以做到代码复用。注意:“构造方法1”和“构造方法2” 都是在同一个类当中。最常用的就是无参构造调用有参构造!

⭐️this() 这个语法作用是什么? 代码复用。
⭐️死记硬背对于this()的调用只能出现在构造方法的第一行。

❤️例1

需求:
    1、定义一个日期类,可以表示年月日信息。
    2、需求中要求:
        如果调用无参数构造方法,默认创建的日期为:1970年1月1日。
        当然,除了调用无参数构造方法之外,也可以调用有参数的构造方法来创建日期对象。

public class ThisTest04{
	public static void main(String[] args){
		// 调用无参数构造方法
		Date d1 = new Date();
		d1.detail();

		// 调用有参数构造方法
		Date d2 = new Date(2008, 8, 8);
		d2.detail();
	}
}

class Date{ // 以后写代码都要封装,属性私有化,对外提供setter and getter
	private int year;
	private int month;
	private int day;

	// 构造方法无参
	// 调用无参数构造方法,初始化的日期是固定值。
	public Date(){
		// System.out.println(11);//错误: 对this()的调用必须是构造器中的第一个语句
		/*
		this.year = 1970;
		this.month = 1;
		this.day = 1;
		*/
		this(1970, 1, 1);
//this只能出现在第一行!利用this从一个构造方法调用另一个构造方法;进行代码复用
	}
	// 构造方法有参数
	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;
	}
}

❤️this小总结

⭐️this是一个关键字,是一个引用,保存内存地址指向自身。
⭐️this可以使用在实例方法中( this. ),也可以使用在构造方法中( this() )!
⭐️this出现在实例方法中其实代表的是当前对象。
⭐️this不能使用在静态方法中
⭐️this. 大部分情况下可以省略,但是用来区分局部变量和实例变量的时候不能省略。
⭐️this() 这种语法只能出现在构造方法第一行,表示当前构造方法调用本类其他的构造方法,目的是代码复用。

🥅小试牛刀

❤️例1

(1)定义丈夫类 Husband 和妻子类 Wife,
         丈夫类的属性包括:身份证号,姓名,出生日期,妻子。
         妻子类的属性包括:身份证号,姓名,出生日期,丈夫。
(2)分别给这两个类提供构造方法(无参数构造方法和有参数构造方法都要提供),编写测试程序,创建丈夫对象,然后再创建妻子对象,丈夫对象关联妻子对象,妻子对象关联丈夫对象,要求能够输出这个“丈夫对象”的妻子的名字,或者能够输出这个“妻子对象”的丈夫的名字。并且要求在程序中演示出空指针异常的效果。

public class Test{
	public static void main(String[] args){
		//创建丈夫对象---调用有参构造方法
		Husband h = new Husband("123456","张三","1999-1-14",null);
		/*//第二种---------调用另一种有参构造方法也行
		Husband h = new Husband("123456","张三","1999-1-14");
		*/
		//创建妻子对象--调用有参构造方法
		Wife w = new Wife("456789","李四","2000-6-04",null);//这里null也可以换成h,在这里就把妻子和丈夫关联上
		//让两者产生关联
		h.wife = w;
		w.husband = h;
		//打印
		System.out.println(h.name+"妻子是"+h.wife.name);
		System.out.println(w.name+"丈夫是"+w.husband.name);
		
	}
}


//---------------创建丈夫类
class Husband{
	String idCard;
	String name;
	String birth;
	Wife wife;

	//无参构造方法
	public Husband(){
	}
	//第一种----------有参构造方法
	public Husband(String s1,String s2,String s3,Wife w){
		idCard = s1;
		name = s2;
		birth = s3;
		wife = w;
	}
/*
	//第二种----------有参构造方法
	public Husband(String s1,String s2,String s3){//最后一个不写,默认赋值上null
		idCard = s1;
		name = s2;
		birth = s3;
	}
*/
}

//---------------创建妻子类
class Wife{
	String idCard;
	String name;
	String birth;
	Husband husband;
	
	//无参构造方法
	public Wife(){
	}
	//有参构造方法
	public Wife(String s1,String s2,String s3,Husband h){
		idCard = s1;
		name = s2;
		birth = s3;
		husband = h;
	}
}

❤️例2

请通过代码封装,实现如下需求:
    编写一个类Book,代表教材:    
    1.具有属性:名称(title)、页数(pageNum)
    2.其中页数不能少于200页,否则输出错误信息,并赋予默认值200
    3.为各属性提供赋值和取值方法
    4.具有方法:detail,用来在控制台输出每本教材的名称和页数
    5.编写测试类BookTest进行测试:为Book对象的属性赋予初始值,并调用Book对象的detail方法,看看输出是否正确

public class Test01{
	public static void main(String[] args){
		//创建对象
		Book b = new Book("高等数学",180);//页数不够200页
		b.detail();//打印测试
		Book b1 = new Book("大学物理",250);//页数够200页
		b1.detail();//打印测试

		//更改数据
		b1.setPageNum(100);//页数不够200页
		b1.detail();//打印测试
		b1.setPageNum(300);//页数够200页
		b1.detail();//打印测试
		//打印结果
		/*
		页数不够200页,不够200页,默认赋值为200页
		教材名称:高等数学, 教材页数:200
		教材名称:大学物理, 教材页数:250
		页数不够200页,默认赋值为200页
		教材名称:大学物理, 教材页数:200
		教材名称:大学物理, 教材页数:300
		*/
	}
}

//Book类
class Book{
//1. 变量私有化
	private String title;
	private int pageNum;

//2. 构造方法
	public Book(){// 无法构造方法
	}

	public Book(String s,int i){// 有参构造方法
		title = s;
		if(i<200){
			System.out.println("页数不够200页,不够200页,默认赋值为200页");
			pageNum = 200;
		}else{
			pageNum = i;
		}
	}

//3. set和get接口
	public void setTitle(String s){
		title = s;
	}
	public String getTitle(){
		return title;
	}

	public void setPageNum(int i){
		if(i<200){
			System.out.println("页数不够200页,默认赋值为200页");
			pageNum = 200;
			return;
		}
		pageNum = i;
	}
	public int getPageNum(){
		return pageNum;
	}

//4. 测试接口detail
	public void detail(){
		System.out.println("教材名称:"+title+", 教材页数:"+pageNum);//这里实际省略了this.
	}
}

JavaSE基础篇 | static关键字和this关键字

 ❤️例3

写一个名为Account的类模拟账户。该类的属性和方法如下所示:
(1)该类包括的属性:账户id,余额balance,年利率annualInterestRate;
(2)包含的方法:各属性的set和get方法。取款方法withdraw(),存款方法deposit()

写一个测试程序
(1)创建一个Customer,名字叫Jane Smith,他有一个账号为1000,余额为2000,年利率为1.23%的账户
(2)对Jane Smith操作:
        存入100元,再取出960元,再取出2000。
        打印Jane Smith的基本信息
        信息如下显示:
        成功存入:100
        成功取出:960
        余额不足,取钱失败

public class Homework2{
	public static void main(String[] args){
		// 先创建一个账户对象Account
		Account a = new Account("1000", 2000, 1.23);
		// 创建客户对象
		// 传给构造方法a是让Customer对象和Account对象产生关系。
		Customer c = new Customer("Jane Smith", a);

		/*进行测试操作
		对Jane Smith操作:
			存入100元,
			再取出960元,
			再取出2000。
		*/
		c.getAct().deposit(100);
		c.getAct().withdraw(960);
		c.getAct().withdraw(2000);
	}
}

// 以后都是封装,所有的类都是属性私有化,对外提供setter and getter方法。
//1. 创建客户类Customer
class Customer{
	// 客户名字
	private String name;
	// 客户手里应该有银行账户
	private Account act;

//2. 构造方法
	public Customer(){
	
	}
	public Customer(String name, Account act){
		this.name = name;
		this.act = act;
	}

//3. setter and getter方法
	// 为什么要写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;
	}
}

//1. 账户类Account
class Account{
	private String id;
	private double balance;
	private double annualInterestRate;

//2. 构造方法
	public Account(){// 无参构造
	
	}
	public Account(String id, double balance, double annualInterestRate){ // 有参构造
		// 创建对象时需要的代码。
		this.id = id;
		this.balance = balance;
		this.annualInterestRate = annualInterestRate;
	}

//3. setter and getter
	public void setId(String id){
		// 对象创建完之后,想修改id属性调用此方法。
		this.id = id;
	}
	public String getId(){
		return id;
	}
	// 实例方法(需要“引用.”来调用。)
	public void setBalance(double balance){ //修改余额的方法。
		this.balance = balance;
	}
	public double getBalance(){
		return balance;
	}
	public void setAnnualInterestRate(double annualInterestRate){
		this.annualInterestRate = annualInterestRate;
	}
	public double getAnnualInterestRate(){
		return annualInterestRate;
	}

//4. 存款、取款方法
	// 参数表示存多少钱。
	public void deposit(double money){
		// 第一种
		this.balance += money;//this.可省

		// 第二种:调用方法来进行修改余额
		this.setBalance(this.getBalance() + money);//this.可省
		System.out.println("成功存入:" + money);
	}

	// 调用取钱的方法时,应该传递过来一个参数,告诉该方法要取多少钱
	public void withdraw(double money){
		// this(从this指向的对象中取款)
		if(money > this.getBalance()){
			System.out.println("余额不足,取钱失败");
			return;
		}
		// 程序能够执行到此处说明余额充足
		this.setBalance(this.getBalance() - money);
		System.out.println("成功取出:" + money);
	}
}

❤️例4

public class Test03{
	public static void main(String[] args){
//第一种方法
		// 调用无参构造方法
		Student s1 = new Student();
		// 赋值
		s1.setName("张三");
		s1.setAge(20);
		s1.setAddress("北京朝阳区");
		s1.setZipcode("122222");
		s1.setMobile("12235224214");
		//打印
		System.out.println("姓名:"+s1.getName() + "," + s1.getPostAddress());
//第二种方法
		//调用有参构造方法
		Student s2 = new Student("李四",18,"深圳宝安区","111111","456456456456465");
		//打印
		System.out.println("姓名:"+s2.getName() + "," + s2.getPostAddress());
	}
}

//1. 创建Student类-----封装
class Student{
		private String name;
		private int age;
		private String address;
		private String zipcode;
		private String mobile;

//2. 构造方法
		public Student(){
		}
		public Student(String name, int age, String address, String zipcode, String mobile){
			this.name = name;
			this.age = age;
			this.address = address;
			this.zipcode = zipcode;
			this.mobile = mobile;
		}
//4. getPostAddress方法
		public String getPostAddress(){
			return "地址:"+this.getAddress() + ",邮编:"+this.getZipcode();
			//或者 return "地址:" + this.address + ",邮编:" + this.zipcode;
		}

//3. set和get接口
		public void setName(String name){
			this.name = name;
		}
		public String getName(){
			return name;
		}

		public void setAge(int age){
			this.age = age;
		}
		public int getAge(){
			return age;
		}

		public void setAddress(String address){
			this.address = address;
		}
		public String getAddress(){
			return address;
		}

		public void setZipcode(String zipcode){
			this.zipcode = zipcode;
		}
		public String getZipcode(){
			return zipcode;
		}

		public void setMobile(String mobile){
			this.mobile = mobile;
		}
		public String getMobile(){
			return mobile;
		}
}

🏀总结

❤️例1

到目前为止一个类当中可以出现的:
		类体{
			实例变量;
			实例方法;

			静态变量;
			静态方法;

			构造方法;

			静态代码块;
			实例语句块;

			方法(){
				// 局部变量
				int i = 100;
			}
		}
public class Review{ // 类
	// 类加载机制中,是这样的:在程序执行之前,凡是需要加载的类全部加载到JVM当中。
	// 先完成加载才会执行main方法。
	static{
		System.out.println("Review类加载时执行!");
	}

	// 入口
	// 静态方法
	public static void main(String[] args){
		// 局部变量
		int i = 100;

		// 完成一个对象的一连串动作。
		// 一个学生在教室先学习,学习完成之后去餐厅吃饭。
		Student s1 = new Student();

		// 先学习,所有调用学习这个实例方法。
		s1.study();

		Student s2 = new Student();
	}

}

// 学生类
class Student{

	static{
		System.out.println("Student类加载时执行!");
	}

	// 学号
	private int no; // 实例变量
	// 姓名
	private String name;

	// 学生有静态变量吗?
	// 类级别的属性
	static String job = "学习";

	{
		System.out.println("实例语句块,构造方法执行一次,这里就执行一次!");
	}

	// 构造方法
	public Student(){
		// 假设调用无参数的构造方法,默认创建的学生学号是100,名字是zhangsan
		this(100, "zhangsan"); // this() 在这里也使用了。
	}
	public Student(int no, String name){
		this.no = no; // 这里使用了this
		this.name = name;
	}

	// 封装
	// setter and getter方法
	public void setName(String name){
		this.name = name;
	}
	public String getName(){
		return name;
	}
	public void setNo(int no){
		this.no = no;
	}
	public int getNo(){
		return no;
	}

	// 提供两个实例方法
	public void study(){
		// 私有的是可以在本类中访问的。在其它类中必须使用set和get方法。
		//System.out.println(this.name + "正在努力的学习!");
		//System.out.println(name + "正在努力的学习!");

		// 在实例方法中调用本类其它的实例方法。
		System.out.println(this.getName() + "正在努力的学习!");
		//System.out.println(getName() + "正在努力的学习!");

		// 方法执行到此处表示学习完成了,去吃饭。
		//this.eat();		
		// this.可以省略
		// 编译器检测到eat()方法是实例方法,会自动在eat()方法前添加 this.
		eat();
	}
	
	public void eat(){ // 实例方法
		System.out.println(this.getName() + "在餐厅吃饭呢!!!");

		// 调用静态m1()方法
		// 静态方法使用“类名.”的方式访问
		// Student.m1();

		// 类名. 可以省略吗?可以。
		// java编译器会自动在m1()方法之前添加“类名.”,因为检测到m1()方法是一个静态方法。
		m1();
	}


	// 提供两个静态方法
	public static void m1(){
		System.out.println("Student's m1 method execute!");
		// 调用m2()方法
		//Student.m2();
		m2();
	}

	public static void m2(){
		System.out.println("Student's m2 method execute!");
		System.out.println("工作性质:" + job);
		// 编译器检测到job是一个静态变量,所以这里会自动在job前添加:Student.
		//System.out.println("工作性质:" + Student.job);
	}
}

❤️例2

(1)程序再怎么变化,万变不离其宗,有一个固定的规律:
所有的实例相关的都是先创建对象,通过“引用.”来访问。
所有的静态相关的都是直接采用“类名.”来访问。

(2)大结论:只要负责调用的方法a和被调用的方法b在同一个类当中:
this. 可以省略
类名. 可以省略


public class Review02{

	int i = 100;

	static int j = 1000;

	public void m1(){

		// 访问其他类的静态方法
		T.t1();

		// 访问其他类的实例方法
		T t = new T();
		t.t2();
	}

	public void m2(){}

	// 实例方法
	public void x(){ // 这个方法是实例方法,执行这个方法的过程中,当前对象是存在的。对象调用这个方法
		m1(); //可以的,默认会加上this.
		m2();

		m3();
		m4();

		System.out.println(i); // System.out.println(this.i);
		System.out.println(j); // System.out.println(Review02.i);
	}

	public static void m3(){}

	public static void m4(){}

	// 问?你怎么分析这个程序?
	/*
		第一步:
			main方法是静态的,JVM调用main方法的时候直接采用的是“类名.”的方式。
			所以main方法中没有this。

		第二步:
			m1() 和 m2() 方法是实例方法,按照java语法规则来说,实例方法必须先
			new对象,通过“引用.”的方式访问。
	*/
	public static void main(String[] args){
		// 编译报错。
		//m1(); //默认加上this.但是是static方法,不行
		//m2();

		m3(); // 编译器会自动识别m3()静态方法,结果是:Review02.m3();
		m4(); // Review02.m4();

		//System.out.println(i); // 报错
		System.out.println(j); // 可以

		// 想访问m1() m2()还有i,你在static方法中只能自己new
		Review02 r = new Review02();
		System.out.println(r.i);
		r.m1();
		r.m2();

		// 局部变量,局部变量访问的时候是不需要“xxx.”的
		int k = 10000;
		System.out.println(k);
	}
}


class T{
	// 静态方法
	public static void t1(){
	
	}

	//实例方法
	public void t2(){
	
	}
}

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/128497.html

(0)
飞熊的头像飞熊bm

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!