JavaSE 基础 - 第11章 this和static

1、static关键字

1.1、static修饰的统一都是静态的,都是类相关的,不需要new对象。直接采用“类名.”访问。

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

		成员变量又可以分为:
			实例变量
			静态变量

【例】

class VarTest{

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


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

1.2 什么时候变量声明为实例的,什么时候声明为静态(static)的?

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

	一个对象一份的是实例变量。
	所有对象一份的是静态变量。

   【总结】:当一个属性是类级别的属性,并且所有对象的这个属性的值是一样的,建议定义为静态变量
016-变量什么时候声明为静态变量
017-变量什么时候声明为静态的2
   【重点】java中一共有三种变量:局部变量、实例变量、静态变量
      局部变量:在方法体中声明的变量 -----》保存在 栈stack
      实例变量: 对象级别 ----》保存在 堆内存 中-----先new对象,再通过“引用.”的方式访问
      静态变量: static 类级别 ----》保存在 方法区 中 ----通过“类名.”的方式访问

      成员变量: 在方法体外声明的变量(分为实例变量和静态变量)

1.3 空引用访问静态 不会出现空指针异常!

	实例的:一定需要使用“引用.”来访问(先new对象)。

	静态的:
		建议使用“类名.”来访问,但使用“引用.”也行(不建议使用"引用.")。
		静态的如果使用“引用.”来访问会让程序员产生困惑:程序员以为是实例的呢。
	
	结论:
		空指针异常只有在什么情况下才会发生呢?
			只有在“空引用”访问“实例”相关的,都会出现空指针异常。

1.4 总结一个类中出现的东西

从第一天开始讲解HelloWorld到目前为止,一个类当中一共就写过这些东西。

	类{
		// 实例相关的都是需要new对象的,通过"引用."访问。
		实例变量;
		实例方法;

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

1.5 关于实例方法的调用

	关于方法来说,什么时候定义为实例方法?什么时候定义为静态方法?
		有没有参考标准。

		此方法一般都是描述了一个行为,如果说该行为必须由对象去触发。
		那么该方法定义为实例方法。

	       【参考标准】:
			当这个方法体当中,直接访问了实例变量,这个方法一定是实例方法。就不能加static了

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

			什么是工具类?????
				以后讲。(工具类就是为了方便编程而开发的一些类。)
	
	类 = 属性 + 方法
		属性描述的是:状态
		方法描述的是:行为动作
	
	一个方法代表了一个动作。

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

1.6 静态代码块

	1、使用static关键字可以定义:静态代码块
	2、什么是静态代码块,语法是什么?
		static {
			java语句;
			java语句;
		}
	3、static静态代码块在什么时候执行呢?
		类加载时执行。并且只执行一次。
		静态代码块有这样的特征/特点。

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

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

	6、静态代码块有啥作用,有什么用?
		第一:静态代码块不是那么常用。(不是每一个类当中都要写的东西。)
		第二:静态代码块这种语法机制实际上是SUN公司给我们java程序员的一个特殊的时刻/时机。
		           这个时机叫做:类加载时机。

	具体的业务:
		项目经理说了:大家注意了,所有我们编写的程序中,只要是类加载了,请记录一下类加载的日志信息
		          (在哪年哪月哪日几时几分几秒,哪个类加载到JVM当中了)。
		思考:这些记录日志的代码写到哪里呢?
			写到静态代码块当中。

1.7 目前为止,所有java程序,有顺序要求的是哪些?

	第一:对于一个方法来说,方法体中的代码是有顺序的,遵循自上而下的顺序执行。
	第二:静态代码块1和静态代码块2是有先后顺序的。
	第三:静态代码块和静态变量是有先后顺序的。

	栈:方法只要执行,会压栈。(局部变量)
	堆:new出来的对象都在堆中。垃圾回收器主要针对。(实例变量)
	方法区:类的信息,字节码信息,代码片段。(静态变量)

	方法的代码片段放在方法区,但是方法执行过程当中需要的内存在栈中。

	静态变量在什么时候初始化?类加载时初始化。
	静态代码块什么时候执行?   类加载时执行。
	实例变量,在构造方法执行时内存空间才会开辟。

1.8 实例语句块

	1、除了静态代码块之外,还有一种语句块叫做:实例语句块
	2、实例语句在类加载是并没有执行。
	3、实例语句语法?
		{
			java语句;
			java语句;
			java语句;
		}
	4、实例语句块在什么时候执行?
		只要是构造方法(方法名与类名相同的方法,详情看  【第九章 第7点】)执行,必然在
		构造方法执行之前,自动执行“实例语句块”中的代码。
		      即如果有n个构造方法执行,则有n个实例语句块执行了
			实例语句块 执行;
			构造方法1 执行;
			实例语句块 执行;
			构造方法2 执行;
			实例语句块 执行;
			构造方法3 执行;
			。。。。
			实例语句块 执行;
			构造方法n 执行;

		实际上这也是SUN公司为java程序员准备一个特殊的时机,叫做对象构建时机。

【例】 InstanceCode.java

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、代码执行顺序

   如果一个类中有 静态代码块、实例语句块、构造方法、主方法等等,它的执行顺序是怎么样的?
【例】CodeOrder.java

//判断以下程序的执行顺序
public class CodeOrder{
	
	// 静态代码块1
	static{
		System.out.println("A");
	}

	// 入口
	//最终顺序: A X Y C B Z
	public static void main(String[] args){
		System.out.println("Y");
		new CodeOrder();
		System.out.println("Z");
	}

	// 构造方法
	public CodeOrder(){
		System.out.println("B");
	}

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

	// 静态代码块2
	static {
		System.out.println("X");
	}

}

【代码执行顺序-总结】
   1、多个静态代码块按代码顺序执行
      静态代码块1
      静态代码块2
         …
   2、main方法 开始 执行
   3、实例语句块 执行
   4、构造方法1 执行
   5、实例语句块 执行
   6、构造方法2 执行
         …
   7、main方法 结尾 执行

3、this关键字

3.1 this.

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

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

	4、this关键字大部分情况下可以省略,什么时候不能省略呢?
		在实例方法中,或者构造方法中,为了区分局部变量和实例变量,
		这种情况下:this. 是不能省略的。
		
	  【例】public void setNo(int no){ 
			//no是局部变量
			//this.no 是指的实例变量。
			this.no = no; // this. 的作用是:区分局部变量和实例变量。
		}

	5、为什么this不能使用在静态方法中??????
		this代表当前对象,静态方法中不存在当前对象。

【例1】ThisTest01.java:

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

015-this关键字
【例2】 ThisTest02.java

// 分析: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);
	}
}

【例3】 ThisTest03.java 3

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

3.2 this()

	1、this除了可以使用在实例方法中,还可以用在构造方法中。
	2、新语法:通过当前的构造方法去调用另一个本类的构造方法,可以使用以下语法格式:
		this(实际参数列表);
			通过一个构造方法1去调用构造方法2,可以做到代码复用。
			但需要注意的是:“构造方法1”和“构造方法2” 都是在同一个类当中。
		
		【例】
			// 构造方法无参
			// 调用无参数构造方法,初始化的日期是固定值。
			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;
			}

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

3.2 【this 总结】

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

4、【总结】:目前为止,所有的变量怎么访问?所有的方法怎么访问?

java中的三大变量:
018-java中的三大变量

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

		静态变量;
		静态方法;

		构造方法;

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

		方法(){
			// 局部变量
			int i = 100;
		}
	}

【实例1】

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

/*执行结果:
Review类加载时执行!
Student类加载时执行!
实例语句块,构造方法执行一次,这里就执行一次!
zhangsan正在努力的学习!
zhangsan在餐厅吃饭呢!!!
Student's m1 method execute!
Student's m2 method execute!
工作性质:学习
实例语句块,构造方法执行一次,这里就执行一次!
*/
2、程序再怎么变化,万变不离其宗,有一个固定的规律:
		所有的实例相关的都是先创建对象,通过“引用.”来访问。
		所有的静态(static)相关的都是直接采用“类名.”来访问。
	
	你有发现一些问题吗?
		总有一些是需要记忆的,在这些记忆的基础之上进行分析。
	
	大结论:
		只要负责调用的方法a和被调用的方法b在同一个class类当中:
			this. 可以省略  --编译器检测到a()方法是实例方法,会自动在a()方法前添加 this.
			类名. 可以省略  --编译器检测到a()方法是静态方法。会自动在a()方法前添加“类名.”

【实例2】

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

传送门

上一章:JavaSE 基础 - 第十章 封装
下一章:JavaSE 基础 - 第十二章 继承

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
面向对象编程是一种编程范式,它将程序的构建和设计思路以面向对象的方式进行组织和实现。在Java中,面向对象编程是基于Java SE(Standard Edition)的一种编程方式。第07讲主要介绍了面向对象编程中的一些基本概念和关键术语。 在面向对象编程中,我们将程序中的数据和对数据的操作(方法)封装在一起,形成一个对象。对象由两部分构成:属性和方法。属性是用来描述对象的特征,而方法则是对象可以执行的操作。对象之间通过消息(方法调用)进行通信和交互。面向对象的核心思想是通过封装、继承和多态实现程序的复用和扩展。 封装是面向对象编程中的一个重要概念,它指的是将类的属性和方法进行封装,使得外部无法直接访问和修改对象的内部状态,只能通过公共的方法来操作属性和执行方法。封装提供了一种将数据和行为组合在一起的方式,可以保护数据的完整性和安全性。 继承是面向对象编程中的另一个重要概念,它指的是通过定义一个新的类来继承现有类的属性和方法。通过继承,子类可以继承父类的属性和方法,并可以在此基础上进行扩展和修改。继承提供了一种代码复用的机制,可以减少重复编码的工作量。 多态是面向对象编程的又一个重要概念,它指的是同一类型的对象在不同的情况下可以有不同的表现形式。多态通过方法的重写和方法的重载实现。方法的重写指的是在子类中重新定义和实现父类的方法,方法的重载指的是在同一个类中可以定义多个同名但参数列表不同的方法。 总结来说,面向对象编程是一种将程序组织和设计思路以对象为中心的编程方式。在JavaSE中,我们可以通过封装、继承和多态来实现面向对象编程的目标。封装可以提高程序的可维护性和可复用性,继承可以减少重复编码的工作量,多态可以灵活地操作对象。掌握这些基本概念和关键术语,可以帮助我们更好地理解和应用面向对象编程的思想。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值