对于static关键字从第一天开始就见到了。在Java里面,static可以定义属性、方法。
1.1、使用static定义属性
下面首先来观察一个程序类,要求定义出一个表示所有清华大学学校的学生信息,那么就证明学生类里面需要提供一个学校的信息,表示所在的学校,所以按照之前学习的内容,代码开发如下。
class Student {
private String name ;
private int age ;
String school = "清华大学" ; // 此处为了方便,暂不封装
public Student(String name,int age) {
this.name = name ;
this.age = age ;
}
public String getInfo() {
return "姓名:" + this.name + ",年龄:" + this.age + ",学校:" + this.school ;
}
}
public class TestDemo {
public static void main(String args[]) {
Student stuA = new Student("张三",20) ;
Student stuB = new Student("李四",21) ;
Student stuC = new Student("王五",22) ;
System.out.println(stuA.getInfo()) ;
System.out.println(stuB.getInfo()) ;
System.out.println(stuC.getInfo()) ;
}
}
此时每个对象之中都占有一个“school”的属性,而且这些属性只要是通过Student类产生的对象,都应该是相同的。那么如果说现在Student类产生了10W个对象。则需要同时对10W个对象的school属性内容进行修改。所以这个时候的设计就不合理了,应该将school这个属性作为一个公共属性出现。这样不仅节省了空间,而且方便数据的统一维护。
在这种情况下就可以使用static关键字来声明了,即:使用static关键字声明的属性就是公共属性。
范例:使用static修改
class Student {
private String name ;
private int age ;
static String school = "清华大学" ; // 此处为了方便,暂不封装
public Student(String name,int age) {
this.name = name ;
this.age = age ;
}
public String getInfo() {
return "姓名:" + this.name + ",年龄:" + this.age + ",学校:" + this.school ;
}
}
public class TestDemo {
public static void main(String args[]) {
Student stuA = new Student("张三",20) ;
Student stuB = new Student("李四",20) ;
Student stuC = new Student("王五",20) ;
stuA.school = "北京大学" ;
System.out.println(stuA.getInfo()) ;
System.out.println(stuB.getInfo()) ;
System.out.println(stuC.getInfo()) ;
}
}
当修改一个对象的school属性的时候所有对象的school属性都修改了,就得出一个结论:school是一个公共属性。而此属性不再保存在堆内存之中,会保存在一个称为“全局数据区”的内存区域,此时内存关系图如下。
以上的程序是通过一个对象修改了公共属性,严格来讲这样并不好,既然是公共属性,那么就必须由所有对象最高代表进行操作,那么所有对象的最高代表就是类,那么一般使用static定义的属性往往会通过类名称直接调用。
Student.school = "北京大学" ;
正是由于static存在这样的由类名称直接调用的特点,所以static属性又被称为“类属性”,而且static属性可以在一个类没有实例化对象的时候直接进行访问。
public class TestDemo {
public static void main(String args[]) {
System.out.println(Student.school) ;
Student.school = "北京大学" ;
System.out.println(Student.school) ;
}
}
那么现在就会发现在类之中的属性就分为两种:普通属性、static属性,那么在设计的时候优先考虑的是普通属性,在99%的设计之中,都会出现普通属性,而只有在1%的情况下才会出现static属性。
1.2、使用static定义方法
既然使用static定义的属性可以通过类名称直接访问,那么使用static定义的方法也一定可以通过类名称直接访问,而且使用static定义的方法其主要目的就是为了操作static属性。
范例:观察static方法的使用
class Student {
private String name ;
private int age ;
private static String school = "清华大学" ;
public Student(String name,int age) {
this.name = name ;
this.age = age ;
}
public static String getSchool() {
return school ; // 没有加上this
}
public static void setSchool(String sch) { // 名称不统一
school = sch ; // 没有加上this
}清华大学JAVA基础
public String getInfo() {
return "姓名:" + this.name + ",年龄:" + this.age + ",学校:" + this.school ;
}
}
public class TestDemo {
public static void main(String args[]) {
System.out.println(Student.getSchool()) ;
Student.setSchool("北京大学") ;
Student stu = new Student("张三",20) ;
System.out.println(stu.getInfo()) ;
}
}
首先在开发之中肯定优先选用普通方法,但是对于类之中的方法现在就存在有两类:普通方法、static方法,而这两类方法调用上是有限制的:
· 使用static方法只能够调用static属性和static方法,不能够调用任何的非static操作;
· 使用非static方法可以调用任意的static属性或static方法。
思考:以上的限制只是语法层次上的限制,那么下面再通过实际的道理来分析以上问题?
首先static方法和非static方法调用的时机是不同的。Static方法可以由类名称直接调用,那么在调用的时候可以没有实例化对象产生,而非static方法,必须在有实例化对象产生之后才可以调用(对象实例化之后会开辟堆内存空间,在堆内存空间之中要保存属性的信息)。
通过以上的一系列分析可以发现,虽然static定义的属性和方法是在类之中定义的,但是却对立于类之外,不受类对象的控制。那么只有在一种情况下会选择定义static方法:如果一个类之中没有任何的属性存在,那么就可以考虑将所有的方法都定义为static。
1.3、观察主方法(理解)
在第一天讲解Java方法定义的时候曾经这样解释过:“如果现在一个方法定义在主类之中,并且由主方法直接调用”的话,则方法定义格式如下:
public static 返回值类型 方法名称(参数列表) {
[return [返回值] ;]
}
而后来定义类的时候发现方法上并没有编写static,那么下面做一个总结说明。
范例:在主类里编写方法
public class TestDemo {
public static void main(String args[]) { // static方法
// static方法只能够调用static属性或者是static方法
fun() ; // 调用static方法,直接调用
}
public static void fun() {
System.out.println("Hello World .") ;
}
}
那么如果此时fun()方法上没有static,则表示static方法(main())要去调用非static方法(fun()),这样是无法进行调用的。那么这个时候fun()就是一个普通方法,如果是普通方法就只能通过实例化对象调用。
public class TestDemo {
public static void main(String args[]) { // static方法
new TestDemo().fun() ;
}
public void fun() {
System.out.println("Hello World .") ;
}
}
而现在就可以发现一个小问题,在Java里面的主方法似乎是长了点,所以下面来分析一下主方法的组成:
· public:这是一种权限,表示公共的,都可以访问;
· static:表示此方法可以由类名称直接调用;
· void:主方法是一切的开始,只要开头了,就没回头路了;
· main():是一个系统默认定义好的方法名称,使用java解释类的时候默认找到此名称;
· String args[]:接收的参数。
范例:接收参数
public class TestDemo {
public static void main(String args[]) {
for (int x = 0 ; x < args.length ; x ++) {
System.out.print(args[x] + "、") ;
}
}
}
所有的参数在解释类的时候通过空格分割:“Java TestDemo 参数 参数 参数 …”,但是有一点需要注意,既然所有的参数之间必须使用“空格”分割,如果说现在参数本身就存在有空格呢?则必须使用“"”声明(java TestDemo "hello world" "hello mldn")。
1.4、static的使用(理解)
在实际的工作里面,static绝对不是优先使用的,而且几乎用的很少,那么下面通过两个简单的程序,巩固一下static的使用。
功能一:作为统计记录使用
如果说现在有一个类要求可以统计出类之中产生过多少个实例化对象,则就可以利用static进行统计。由于每个新对象实例化的时候一定要调用构造方法,所以可以在构造方法里面增加统计操作。
class Person {
private static int count = 0 ; // 统计个数
public Person() {
System.out.println("Person对象个数:" + ++ count) ;
}
}
public class TestDemo {
public static void main(String args[]) {
new Person() ; new Person() ; new Person() ;
new Person() ; new Person() ; new Person() ;
}
}
功能二:实现对象的自动命名
假设现在Person类里面有一个name属性,同时提供有两个构造方法(无参、一个参数),通过一个参数可以由外部设置人的名字,但是如果调用的是一个无参构造,则不希望name属性的内容是null,给他一个默认的名字“无名氏-编号”,那么这个编号不应该重复,所以就可以利用static统计。
class Person {
private static int count = 0 ; // 统计个数
private String name ;
public Person() {
this("无名氏 - " + count ++) ; // 自动命名
}
public Person(String name) {
this.name = name ;
}
public String getName() {
return this.name ;
}
}
public class TestDemo {
public static void main(String args[]) {
System.out.println(new Person().getName()) ;
System.out.println(new Person("张三").getName()) ;
System.out.println(new Person().getName()) ;
}
}
日后如果见到了有类似的操作,要能够分析出使用了static即可,其它的东西意义不大。
版权声明:
本文来源网络,所有图片文章版权属于原作者,如有侵权,联系删除。
本文网址:https://www.bianchenghao6.com/h6javajc/20524.html