阿里云名师课堂Java面向对象开发44 ~ 46:static关键字

Posted 溺水的情书

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了阿里云名师课堂Java面向对象开发44 ~ 46:static关键字相关的知识,希望对你有一定的参考价值。

44:static属性

在讲解之前首先观察一道程序:

  • 范例:定义一个表示人的类,同时设置他所在的国家
class Person{
	private int age	;
	private String name ;
	String country = "China";  // 为了后面的操作方便,暂时不封装,当然这样是不对的
	
	public Person(String name,int age) {
		this.age = age ;
		this.name = name ;
	}
	
	public String getInfo() {
		return "【PERSON】姓名:" + this.name + 
		",年龄:" + this.age + ",国家:" + this.country;
	}
}

public class TestDemo {
	public static void main(String args[]) {
		Person p1 = new Person("Dexter",20) ;
		Person p2 = new Person("Tsukishima Kei",18) ;
		Person p3 = new Person("Toono Takaki",19) ;
		System.out.println(p1.getInfo()) ;
		System.out.println(p2.getInfo()) ;
		System.out.println(p3.getInfo()) ;
	}
}

技术图片
下面对这三个对象进行内存分析:
技术图片
既然描述的country都是China,那么理论上这些country属性是相同的,此时可以发现每一个对象的country属性被重复保存了。
那么假如国家的名称要换个表示方法(英文?中文、简写?全称之类),按以上的储存方式就会出现一个问题:

  • 假设当前Person类已经产生了十亿个对象,而需要把名称换为中文表示,要通过对象.country = "中文名" ;操作十亿次来改变。
public class TestDemo {
	public static void main(String args[]) {
		······
		p1.country = "中国" ;
		······
	}
}

技术图片
现在可以发现传统属性具备的特征:保存在堆内存之中,每一个对象独享此属性。可是同样的概念明显不适合于当前的情况,所以最好的做法是将country属性变为一个共享属性,那么只要一次修改就可以影响到所有的对象。

  • 而如果要将属性变为共享属性,只要在属性前追加一个static关键字即可。
class Person{
	······
	static String country = "China";  // 为了后面的操作方便,暂时不封装
	······
	}
}

public class TestDemo {
	public static void main(String args[]) {
		······
		p1.country = "中国" ;
		······
	}
}

技术图片
当程序中使用了static关键字进行定义之后,此属性不会保存在堆内存之中,而是在名为全局数据区的内存空间之中,并且所有对象都可以进行该数据区的访问。
技术图片
既然使用的是共享属性,有一个问题:共享属性能通过一个对象修改吗?

  • 虽然上面代码通过对象p1修改static属性country,但实际上正确操作应该是类名.属性 = "修改" ;
  • static实际上可以称为类属性,而所有类属性都可以通过类名称直接调用。
  • 结论:访问static属性使用类名称

所有的非static属性必须在产生实例化对象之后才可以使用,而所有static属性不受实例化的限制,也就是说是否有对象与static属性的操作无关。

  • 选择:关于static属性与非static属性的选择
    • 在定义类时99%的情况下是不会考虑static属性的;
    • 只有在需要描述共享属性的概念或者希望不受实例化控制时使用static

45:static方法

既然通过static定义的属性可以被类名称直接访问,那么static定义的方法也可以被类名称直接访问,同样不受实例化的限制。
范例:观察static定义的方法

class Person{
	private int age	;
	private String name ;
	private static String country = "China";  // 为了后面的操作方便,暂时不封装
	
	public Person(String name,int age) {
		this.age = age ;
		this.name = name ;
	}
	
	public static void setCountry(String c){
		country = c ;
	}
	public String getInfo() {
		return "【PERSON】姓名:" + this.name + 
		",年龄:" + this.age + ",国家:" + this.country;
	}
}

public class TestDemo {
	public static void main(String args[]) {
		Person p1 = new Person("Tsukishima Kei",18) ;
		System.out.println(p1.getInfo()) ;
		Person.setCountry("中国") ;
		System.out.println(p1.getInfo()) ;
	}
}

技术图片
现在类中既有static方法又有非static方法,那么这时对于两者的互相调用存在两点限制:

  1. 所有static方法不允许调用非static属性或者方法;
	public static void setCountry(String c){
		name = "avasd" ;
		country = c ;
	}
	// 编译报错,错误: 无法从静态上下文中引用非静态 变量 name
	public static void setCountry(String c){
		getInfo() ;
		country = c ;
	}
	// 编译报错,错误: 无法从静态上下文中引用非静态 方法 getInfo()
  1. 所有的非static方法允许访问static属性或方法
	public String getInfo() {
		setCountry("中国中国") ;
		return "【PERSON】姓名:" + this.name + 
		",年龄:" + this.age + ",国家:" + this.country;
	}

技术图片
原因:因为所有的static方法可以在没有实例化对象的时候访问,而所有的非static操作必须在有实例化对象之后才可以进行。
使用static属性的目的是共享,因为属性都需要封装。而是用static方法的目的在于:某些方法不希望受到类的限制,即希望可以在没有实例化对象的时候执行。

46:分析主方法组成

如果一个方法定义在主类之中,并且由主方法直接调用,那么该方法的定义语法如下:

  • public static 返回值类型 方法名称(参数列表) {}

后来进行类的学习时没有用到static(非主类中),主要原因是static方法的限制。
观察Java主方法名的组成:

  • public static void main(String args[]) {}
  • public:表示是公用的,因为主方法作为程序起点必须可以随意访问;
  • static:执行Java程序时执行的是一个类名称,所以表示不受实例化对象限制;
  • void:主方法作为程序起点,是栈中最底层的函数,所以并不存在能够接收的值(没有谁能接收main的返回值);
  • main:是一个系统定义好的方法名称(主方法默认名称);
  • String args[]:表示该类执行时所需要的相关参数。
    • 范例:取得执行参数
public class TestDemo {
	public static void main(String args[]) {  // 所有参数类型都是String型
		for(int x = 0 ; x < args.length ; x++){
			System.out.println(args[x]) ;
		}
	}
}
  • 通过如图所示方式进行参数设置,可以看到没有设置参数时没有任何输出。
    技术图片














以上是关于阿里云名师课堂Java面向对象开发44 ~ 46:static关键字的主要内容,如果未能解决你的问题,请参考以下文章

阿里云名师课堂Java面向对象开发79 ~ 81:包装类

阿里云名师课堂Java面向对象开发74:匿名内部类

阿里云名师课堂Java面向对象开发3 ~ 6:类与对象

阿里云名师课堂Java面向对象开发3 ~ 6:类与对象

阿里云名师课堂Java面向对象开发68 ~ 7073:接口的定义和使用

阿里云名师课堂Java面向对象开发7:private实现封装处理