阿里云名师课堂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方法,那么这时对于两者的互相调用存在两点限制:
- 所有static方法不允许调用非static属性或者方法;
public static void setCountry(String c){
name = "avasd" ;
country = c ;
}
// 编译报错,错误: 无法从静态上下文中引用非静态 变量 name
public static void setCountry(String c){
getInfo() ;
country = c ;
}
// 编译报错,错误: 无法从静态上下文中引用非静态 方法 getInfo()
- 所有的非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关键字的主要内容,如果未能解决你的问题,请参考以下文章