深入Java类、对象 与 Static

11年前

深入Java类、对象与Static

 今日闲来无事,室外都快成烤箱了。。。So,没事做就仔细研究了一下Java的类、对象和Static的关系。刚开始学习Java的时候,对着Core Java看,看了好久也没明白什么是类,什么是对象,还有这个头疼的Static。随着工作了一段时间,类和对象这些概念有了一些理解,但一直没有仔细深入的分析。期间也在网上、各大论坛求解过像Static做用什么的,但一直不得要旨。今天就来仔细总结一下。随着发掘的深入,我发现Java的类、对象和Static这三个概念是密切相关的,他们不能分开。

 在面向对象中,有两个重要概念:类和对象。对象也被称作“实例(instance)”那么究竟什么是类?类是某一批对象的抽象。对象是一个具体存在的实体。我这么说,你看懂了吗?我觉得可能大部分人还是看不懂,因为这个定义太特么抽象了。你是不是再说:“U TM Say What 呢?” Well~ Keep Easy~ 一会儿我用“人”类来给你做个解释。

 重定义你的观念 -> 接口:在JavaC#中,接口这个概念可不是你想的那么简单。在很多书和论坛中大家对接口的一般定义为:比抽象类更加彻底的抽象类-interface。接口里不能包含普通方法,只能是抽象方法云云。但是这里我要告诉你的是:接口,他代表了一个类型!就是说:你这个类,只要实现了我的接口,你便拥有了我的类型特征。Java中提倡单一继承,多重实现。你可以implements多个接口,也就是说你定义的类将拥有多重类型特征。比如在代码程序中我们定义了一个接口:Person,他的实现类是YellowPerson你在编程的时候可能会用到类型匹配的逻辑,比如:如果你的类是Person类,那么执行代码逻辑。YellowPerson  yp = new YellowPerson();  if(yp.IsPartTypeOf (Person)) ……当然这里的IsPartTypeOf方法是你要自己写的。接口作为顺带介绍,与本文关联并不大。你要知道他还有类型的意义就够了。下面用代码说明类、对象和Static

public interface Person

{

              void say();

              void head();

              void body();

              void armsAndlegs();//四肢

             

              public static final int eyes =2;

              public static final int mouth = 1; 

}

public class YellowPerson implements Person

       private static int ears = 2; 

       private static int nose = 1;

      

       private String sex ;

       private String skin

        

       public void head()

       {

              System.out.println("我继承了人类,我有:" + this.eyes 

                            +  " 眼睛和 " + this.mouth + " 张嘴");

       }

       public void body()

       {

              System.out.println("我还有: " + ears  + " 耳朵;: " +

                            nose + " 个鼻子");

       }

      

       public void armsAndlegs()

       { 

              String a = getSex();

              String b = getSkin();

              System.out.println("人的性别和肤色是不固定的,我是 " + a + b+ "皮肤");

       }

       public void say()

       {

              this.head();

              this.body();

       }

       //########################################

       public String getSex() {

              return sex;

       }

       public void setSex(String sex) {

              this.sex = sex;

       }

       public String getSkin() {

              return skin;

       }

       public void setSkin(String skin) {

              this.skin = skin;

       }

}

public class Test

{

       public static void main(String[] args)

       {

              YellowPerson  yp = new YellowPerson();

              yp.say();

              yp.setSex("男人");

              yp.setSkin("黄色");

              yp.armsAndlegs();

              System.out.println("眼睛数量:"+yp.eyes);

       }

}

打印结果:

我继承了人类,我有:2 眼睛和 1 张嘴

我还有: 2 耳朵;: 1 个鼻子

人的性别和肤色是不固定的,我是 男人黄色皮肤

眼睛数量:2

 

静态变量代表是这个类的固有属性。比如正常人肯定有2个眼睛、一张嘴、2个耳朵,一个鼻子等等。但是这个人的名字、性别、肤色、身高、体重都是不确定的,所以这些不是静态属性。我们在Test.java中调用YellowPerson的时候产生一个对象:ypyp对象中就已经包含了所有 “静态属性” 值:鼻子、眼睛、嘴等等。你用yp直接可以调用该对象包含的static变量,比如:“眼睛数量:2”。但是非静态的普通属性你则需要设定。

也就是说:作为“类”来讲,他定义了很多内容,其中有固定的,有的不是固定的,固定的都是static的;“类”更像是一个模板,而对象则是从这个模板中复制出来的东西。凡是模板都有固定的东西,比如做月饼的模子,他有固定的花纹,但月饼馅不同;“人”这个模板则固定有头、身体、四肢、五官、器官等等static属性,而姓名、性别、身高等等每个人不同,则是普通属性。从这个角度讲:我们日常说的人其实都是“人”这个类的实例(对象),而不是人类。就是说:当你在其他地方调用一个类的时候,他的静态属性已随着对象的初始化复制而出,你直接可以使用,但是普通属性你需要设定,或者更改。比如上述代码中的性别和肤色等。注意:静态属性也可以不通过去创建对象来调用,直接用类名+属性或方法就可以,如:YelloPerson.eyes

       那么对象如何初始化?

    通过构造器,也就是常说的构造函数。每一个类都有一个默认的构造函数。构造函数是用于构造一个类实例的根本途径,即:对象初始化。(顺便提一句方法用于定义类或类实例的行为特征与功能实现。构造函数与方法的区别是没有修饰词。) 你要时刻记得:对象即实例。对象的创建和使用如下,很简单但很容易被忽略:

YellowPerson  yp ; //定义一个YelloPerson类型的变量

yp = new YellowPerson(); //通过new 关键字调用YelloPerson类的构造函数,返回一个类实例

                                   //将实例付给yp变量

因为调用的是类的构造函数,所以YelloPerson后面会有括号。new YellowPerson()即为实例(对象)

    总结一句:你不是人这个类我也不是人这个类,所有活着的人都是“人”的实例(对象)

 



       不得不修改一下,我在写这篇博客的时候,对类、对象、实例和Static的理解存在不足的地方,现在给予纠正。
       首先是对象。在《Think In Java》和《Java核心技术中》给予对象的定义是这样的:“万物皆对象。”  这样放到现实中来讲,包括类以及由类产生的实例都属于对象的范畴。类、对象和类实例之间的关系应该是这样来描述:【类】是一个被定义的模板(包括各种具体属性,如字段、方法);【类实例】是从这个模板中复制出的一个对象;而【对象】应该包括【类】和【类实例】。所以说:“对象即实例”,这句话本身存在缺陷,是错误的。应该这样描述更加确切:【new 一个类的构造函数产生的是一个类实例】,如果你硬说产生的是一个对象,这样也没错,
只不过这样显得空乏,因为对象是一个全集的概念。如下举例:

    yp = new YellowPerson(); //通过new 关键字调用YelloPerson类的构造函数,返回一个类实例   
在上面这段代码中【
通过new 关键字调用YelloPerson类的构造函数,返回一个类实例】这样描述要比【通过new 关键字调用YelloPerson类的构造函数,返回一个“对象”】这个描述更加准确。
       其次是“static”。上文中描述【
静态变量代表是这个类的固有属性】,这也是不确切的,是狭隘的理解,当然就是错的。举例如下:定义一个Person类,类中定义一个静态属性方法:
       public static int nose();
然后分别创建了10个Person类实例,但事实上这10个类实例只有一个nose()方法,并不是每一个类实例都包括了一个自己的nose()方法,即:他们公用一个nose()方法;如果这个比方在现实中发生,那么他们这10个人其实是连体婴儿,因为他们公用一个鼻子。如果在Person类中nose()方法变成非static,而定义一些这样的static方法:air()、water()、sunshine() ,那么会显得更合理一些,也更说的通;因为这些方法是人类共同需要的、无法脱离的。
        在从内存中解释,【static类型属性和方法】在内存中只有一个地址,不是你有多少个类实例就会有多少个地址,你只是引用了这个地址。如果从这个角度讲,那么当你设计一个程序的时候,事实上绝大多数的类是可以不包括【
static类型属性和方法】,而单独的设计一个类专门去做这件事。这样在程序的可读性和可维护性上也会好很多。