java编程思想-一切都是对象

1.一切都是对象  

     尽管Java是基于C++的,但是相比之下,Java 是一种更 纯粹 的面向对象程序设计语言。

     C++和 Java 都是混合/杂合型语言。但是, Java 的设计者认为这种杂合型并不像在C++中那么重要。杂合型语言允许多种编程风格,C++之所以称为一种杂合型语言主要是因为它支持与C语言的向后兼容。因为C++是C的一个超集,所以势必包括许多C语言不具备的特征,这些特征使C++在某些方面显得过于复杂。

      Java 语言假设我们只进行面向对象的程序设计。也就是说,在开始用Java进行设计之前,必须将思想转换到面向对象的世界中来。这个入门基本功,可以使你具备这样一种编程语言的编程能力,这种语言学习起来更简单,也比许多其他OOP语言更易用。

 

2.用引用操控对象

       直接操纵内存中元素的方式,在Java中的到了简化。一切都被视为对象,因此可采用单一固定的语法。尽管一切都看作对象,但操纵的标识符实际上是对象的一个 引用( reference ) ,可以将这一情形想象成用 遥控器(引用) 来操纵电视机(对象)。只要握住这个遥控器,就能保持与电视机的连接。当有人想改变频道或者减少音量时,实际操纵的是遥控器(引用),再由遥控器来调控电视机(对象)如果想在房间内四处走走,同时仍能调控电视机,那么只需携带遥控器(引用)而不是电视机(对象)。  

    此外,即使没有电视机,遥控器亦可独立存在,也就是说,你拥有一个引用,并不需要有一个对象与它关联。因此,如果想操纵一个词或者句子,则可以创建一个 String 引用:如下

String str;

   这里所创建的只是引用,并不是对象。如果此时向 str 发送一个消息,就会返回一个运行时错误。 这是因为此时 str 实际上没有与任何事物相关联。因此,一种安全的做法是 :创建一个引用的同时进行初始化:如下

String str="asdf";

这里用到了Java语言的一个特性:字符串可以用带引号的文本初始化。 通常,必须对对象采用一种更通用的初始化方法。

 

3.必须由你创建所有对象

      一旦创建了一个引用,就希望它能与一个新的对象相关联。通常用 new 操作符来实现这一目的。 new 关键字的意思就是 "给我 一个新对象" ,所以前面的例子可以写成如下:

String str= new String("asdf");

它不仅表示"给我一个新的字符串",而且通过提供一个初始字符串,给出了怎样产生这个 String 信息。

当然,除了String 类型,Java 还提供大量过剩的现成类型。

 

3.1.存储到什么地方

  程序运行时,对象时怎么进行放置安排的呢?特别是内存是怎样分配的呢?对这些方面了解会对你有很大的帮助。有五个不同的地方可以存储数据

1),寄存器。 这是最快的存储区 ,因为它位于不同于其他存储区的地方__处理器内部。但是寄存器的数量及其有限,所以寄存器根据需求进行分配。你不能直接控制,也不能在程序中感受到寄存器存在的任何迹象(另一方面,C和C++允许您向编译器建议寄存器的分配方式)

2),堆栈。位于通用RAM(随机访问存储器)中,但通过 堆栈指针 可以从处理器哪里获得直接支持。堆栈指针若向下移动,则分配新的内存,若向上移动,则释放那些内存。这是一种快速有效的分配存储方法,仅次于寄存器。创建程序时,Java系统必须知道存储在堆栈内所有项的准确生命周期,以便上下移动堆栈指针。这一约束限制了程序的灵活性,所以虽然某些Java数据存储于堆栈中__特别是对象引用,但是Java对象并不存储于其中。

3),。一种通用的内存池(也位于RAM区),用于存放 Java 对象。堆不同于堆栈的好处是:编译器不需要知道存储的数据在堆里存活多长时间。因此,在堆里分配存储有很大的灵活性。当需要一个对象时,只需要 new 写一行简单的代码,当执行这行代码时,会自动在堆里面进行存储分配。当然,为这种灵活性必须要付出相应的代码,用堆进行存储分配和清理可能比堆栈进行储存分配需要更多的时间( 如果确实可以在Java中像在C++中一样在栈中创建对象)

4),常量存储。常量值通常直接存放在程序代码内部,这样做是安全的,因为它们永远不会被改变。有时,在嵌入式系统中,常量本身会和其他部分分隔离开,所以在这种情况下,可以选择将其存放在ROM(只读存储器)中。

5),非RAM存储。如果数据完全存储于程序之外,那么它可以不受程序的任何控制,在程序没有运行时也可以存在。其中俩个基本的例子是流对象持久化对象。在流对象中,对象转化成字节流,通常被发送给另一台机器。在持久化对象中,对象被存放于磁盘上,因此,即使程序终止,它们仍可以保持自己的状态。这种存储方式的技巧在于:把对象转化成可以存放在其他媒介上的事物,在需要时,可恢复成常规的,基于RAM的对象。 Java 提供了对轻量级持久化的支持,而诸如JDBC 和 Hibernate 这样的机制提供了更加复杂的对在数据库中存储和读取对象信息的支持。

 

3.2.特例:基本类型

      在程序设计中经常使用一系列类型,他们需要特殊对待。可以把他们想象成基本类型。之所以特殊对待,是因为 new 将对象存储在 堆 里面,故用new 创建一个对象__特别是小的,简单的变量,往往不是很有效。因此,对于这些特殊类型,Java 和 C++采用了相同的方法。也就是说,不用new 来创建变量,而是创建一个并非引用的 自动 变量。这个变量直接存储值,并置于堆栈中,因此更加高效。

    Java要确定每种基本类型所占存储空间大小。它们的大小并不像其他大多数语言那样随机器硬件架构的变化而变化。这种所占存储空间大小的不变性是Java 程序比用其他大多数语言编写的程序更具可移植性的原因之一。

基本类型 大小 最小值 最大值 包装器类型
boolean   __ __ __ Boolean
char 16-bit Unicode 0 Unicode 2^16-1 Character
byte 8-bits -128 +128 Byte
short 16bites -2^15 +2^15-1

Short

int 32bits -2^31 +2^31-1 Integer
long 64bits -2^63 +2^63-1 Long
float 32bits 1.4E-45 3.4028235E38 Float
double 64bits 4.9E-324 1.7976931348623157E308 Double
void __ __ __ Void
  • 所有的数值类型都有正负号,所以不要去寻找无符号的数值类型。
  • boolean 类型所占存储空间大下没有明确指定,仅定义为能够取字面值 true 和 false。
  • 基本类型具有包装器类,使得可以在堆中创建一个非基本对象,用来表示对应的基本类型。例如
        char c='c';
        Character character1=new Character(c);
        //也可以这样写
        Character character2=new Character('y');

Java SE5自动包装功能将自动地将基本类型转换为包装器类型:

      Character character='x';
      //可以进行反向转换
       char c=character;
       System.out.println(c);

 

3.2.1.高精度数字

       Java 提供了俩个用于高精度计算的类: BigInteger BigDecimal 。虽然它们大体上属于 包装器类 的范畴,但二者都没有对应的基本类型。

        不过,这俩个类包含的方法,提供的操作与对基本类型所能执行的操作相似。也就是说,能作用于 int 或 float 的操作,也同样能作用于BigInteger 或者 BigDecimal 。只不过必须以方法调用方式取代运行符方式来实现。由于这么做复杂了许多,所以运算速度会比较慢。在这里,我们一速度换取了精度。

BigInteger 支持任何精度的整数。也就是说,在运算中,可以准确的表示任何大小的整数值,而不会丢失任何信息。

BigDecimal 支持任何精度的定点数,例如,可以用它进行精确的货币计算。

 

3.3 Java中的数组

      几乎所有的程序设计语言都支持数组。在C和C++中使用数组是很危险的,因为C和C++中的数组就是内存块。如果一个程序要访问其自身内存块之外的数组,或数组初始化前使用内存(程序中常见的错误),都会产生难以预料的后果。

      Java的只要目标之一是安全性,所以许多在C和C++里困扰程序员的问题在Java里就不会出现。Java确保数组会被初始化,而且不能在它的范围之外被访问。这种范围检查,是以每个数组少量的内存开销及运行时的下标检查为代价的。但由此换来的是安全性和效率的提高,因此付出的代价是值得的(并且Java有时可以优化这些操作)。

      当创建一个数组对象时,实际上就是创建了一个引用数组,并且每个引用都会自动被初始化为一个特定值,该值拥有自己的关键字 null 。一旦Java 看到null ,就知道这个引用还没指向某个对象。在使用任何引用前,必须为其指定一个对象,如果试图使用一个还是null的引用,在运行时报错,因此,常见的数组错误在Java中就可以避免。

       还可以创建用来存放基本数据类型的数组。同样,编译器也能确保这种数组的初始化,因为它会将这种数组所占的内存全部置零。

 

4.永远不需要销毁对象

      大多数程序设计语言中,变量生命周期的概念,占据了程序设计工作非常重要的部分,变量需要存活多长时间?如果想要销毁对象,那么时刻进行呢?变量生命周期混乱往往会导致大量的程序bug,本节将介绍Java是怎样替代我们完成所有的清理工作,从而大大地简化这个问题的。

4.1.作用域

  • 大多数过程型语言都有作用域(scope)的概念。作用域决定了再其内定义的变量名的可见性和生命周期。 在C , C++和Java中作用域由 花括号({}) 的位置决定。

4.2.对象的作用域

  • Java 对象不具备和基本类型一样的生命周期。当用new 创建一个Java 对象时,它可以存活于作用域之外。例如
   {
        String s=new String("a String");
    }//End of scope
  1. 引用 s 在作用域终点就消失了。然而, s指向的 String 对象仍继续占据内存空间。在这一小段代码中,我们无法在这个作用域之后访问这个对象,因为对它唯一引用已超出了作用域的范围。
  2. 事实证明,由 new 创建的对象,只要你需要,就会一直保留下去。这样,许多C++编程问题在Java中就完全消失了。在C++中,你不仅需要确保对象的保留时间与你需要这些对象的时间一样长,而且还必须在你使用完它们之后,将其销毁。
  3. 这样便带来一个有趣的问题。如果Java让对象继续存在,那么靠什么才能防止这些对象填满内存空间,进而阻塞你的程序呢?这正是C++里面可能发生的问题。这也是Java神器之所在。Java 有一个垃圾回收器,用来监视用new 创建的所有对象,并辨别哪些不会被引用的对象。随后,释放这些对象的内存空间,以便供其他新的对象使用。也就是说,你根本不需要担心内存回收的问题。你只需要创建对象,一旦不再需要,它们就会自行消息。这样做消除了这类编程的问题(即 内存泄漏) ,这是由程序员忘记释放内存而产生的问题。

4.3.创建新的数据类型:类

  • 大多数面向对象的程序设计语言习惯用 关键字 class 来表示,如下
class HelloWord{ /** Class body goes here*/}

你可以使用 new 来创建这种类型的对象 如下

HelloWord helloWord=new HelloWord();

4.4.字段和方法

  • 一旦定义了一个类(Java中你所做的全部工作就是定义类,产生哪些类的对象,以及发送消息给这些对象),就可以在类中设置俩种类型的元素:字段(有时被称作数据成员) 和 方法(有时被称作成员函数)。字段可以是任何类型的对象,可以通过其引用与其进行通信,也可以是基本类型中的一种。如果字段是对某个对象的引用,那么必须初始化该引用,以便使其与一个实际的对象相关联。
  • 每个对象都有用来存储其字段得空间,普通字段不能再对象间共享。下面是一个具有某些字段得类如下
public class DataOnly {
    int i;
    double d;
    boolean b;
}
  1. 尽管这个类除了存储数据之外什么也不做,但是仍旧可以像下面这样创建它的一个对象。
DataOnly dataOnly = new DataOnly();
  • 可以给字段赋值,但首先必须知道如何引用一个对象的成员。具体的实现为: 在对象引用的名称之后紧接着一个句点,然后再接着是对象内部的成员名称,如下:
        DataOnly dataOnly =new DataOnly();
        dataOnly.i=100;
        dataOnly.b=true;
        dataOnly.d=0.2d;
  • DataOnly 类除了保存数据外没有别的用处,因为它没有任何成员方法。如果你想了解成员方法的运行机制,就得先了解参数和返回值得概念。

基本成员默认值

  • 若类的某个成员是基本数据类型,即使没有进行初始化,Java也会确保它获得一个默认值,如下图
基本数据类型 默认值
boolean false
char

'\uoooo' (null)

byte 0
short 0
long 0L
int 0
float 0.0f
double 0.0d
  • 当变量作为类的成员使用时,Java才确保给定其默认值,一确保那些是基本数据类型的成员变量得到初始化(C++没有此功能),防止产生程序错误。但是,这些初始化对你的程序来说,可能不是正确的,甚至是不合法的。所以你最好明确得对变量进行初始化。
  • 然而上述确保初始化的方法并不适用于 局部 变量(即并非某个类的字段)。如下
    public void setId(){
        int x;
        System.out.println(x);
    }
  1. 那么变量 x 得到的可能是任意值(与C和C++中一样),而不会被自动初始化为零。所以在使用 x前,应先对其赋一个适当的值。如果忘记了这么做,Java就会在编译时返回一个错误,告诉你此时变量没有初始化,这正是Java优于C++的地方。(许多C++编译器会对未初始化变量给予警告,而Java则视为是错误)。

 

5.方法,参数和返回值

       许多程序设计语言(像C和C++)用函数这个术语来描述命名子程序,而在Java里却常用方法这个术语来表示 "做某些事情的方式"。实际上,继续把它看作是函数也无妨。

      Java的方法决定了一个对象能够接受什么样的消息。方法的基本组成部分包括:名称,参数,返回值和方法体。下面是它基本的形式:

ReturnType methodName(/** Argument list*/){
    /** Method body */
}
  • 返回类型描述的是在调用方法之后从方法返回的值。参数列表给出要传给方法的信息的类型和名称。方法名和参数列表(它们合起来被称为 方法签名) 唯一地表示出某个方法。
  • Java中的方法只能做作为类的一部分来创建。方法只有通过对象才能被调用,并且这个对象必须能执行这个方法调用。如果试图在某个对象上调用它并不具备的方法,那么编译时就会得到一条错误信息。

5.1.参数列表

  • 方法的参数列表指定要传递给方法什么样的信息。正如你可能料想的那样,这些信息像Java中其他信息一样,采用的都是对象形式。因此,在参数列表中必须指定每个所传递对象的类型及名字。像Java中任何传递对象的场合一样,这里传递的时机上也是引用,并且引用的类型必须正确。如果参数被设为 String 类型,则必须传递一个String对象,否则,编译器将抛出错误。
  • 若返回类型是 void ,return 关键字的作用只是用来退出方法。因此,没有必要到方法结束时才离开,可在任何地方返回。但如果返回类型不是void ,那么无论在何处返回,编译器都会强制返回一个正确类型的返回值。
  • 你可能觉得: 程序似乎只是一系列带有方法的对象组合,这些方法以其他对象为参数,并发送消息给其他对象。

 

6创建一个Java程序

  • 名字可见性 Java采用一种全新的方法避免模块名字重复的冲突呢? Java设计者希望程序员反过来使用自己的Internet域名。
  • 运用其他构件  import 关键字来准确地告诉编译器你想要的类是什么。
  • static 当声明一个事物是static时,就意味着这个域或方法不会与包含它的那个类的任何对象关联在一起。所以,即使从未创建一个对象,也可以调用其static方法或访问其static域。通常,你必须创建一个对象,并用它来访问数据或者方法。因为非static域和方法必须知道它们一起运作的特定对象。
  • static 方法的一个重要用法就是在不创建任何对象的前提下就可以调用它。

6.1.注释和嵌入式文档

  1. Java有俩种注释风格。一种是传统的C语言风格的注释__C++也继承了这种风格。如下
    /** This is a comment
     *  that continues
     *  across lines
     */

    2.第二种风格也来源于C++。单行注释 如下

// this is a one-line comment

 

6.2.注释文档

  • Javadoc 是用于提取注释的工具,他是JDK安装的一部分。Javadoc命令都只能在 /** 注释中出现,和通常一样,注释结束于 */
  • Javadoc 只能为 public(公开的) 和 protected (受保护的) 成员进行文档注释。
  • Javadoc 中一些标签的使用
  • @see: 引用其他类
  • {@link package.class#member label} 该标签与@see及其相似,只是它只能用于行内,并且使用 label 作为超链接文本而不用 See Also
  • {@docRoot} 该标签产生到文档根目录的相对路径,用于文档树页面的显式超链接
  • {@inheritDoc} 该标签从当前这个类的最直接的基类中继承相关文档到当前的文档注释中
  • @version 可以是你认为合适包含在版本说明中重要信息
  • @author 作者姓名,也可以是电子邮箱或者是其他任何适宜的信息
  • @since 指定程序代码最早使用的版本
  • @param 用于方法文档中 表示传入方法参数
  • @return 用于方法文档中 表示方法返回值类型等信息
  • @description 用来描述返回值的含义 ,可以延续数行
  • @throws 异常,它们是由某个方法调用失败而抛出的对象
  • @deprecated 该标签用于指出一些旧特性已由改进的新特性所取代,建立用户不要在使用这些旧特性,因为在不就将来它们很可能会被删除。 在JavaSE5中 @deprecated 被 @Deprecated注解所取代

 

6.3.编码风格 

  • 在 Java编程语言编码约定 中,代码风格是这样规定的 类名的首字母大写,如果类名由几个单词构成,那么把它们拼在一起,其中每个内部单词的首字母都采用大写形式,如下
class AllTheColorsOfTheRainbow{
    //class body
}
  • 这种风格被称为 驼峰风格 
  • 几乎所有的内容__方法,字段(成员变量),以及对象引用引用名称等,公认的风格与类的风格一样,只是标识符的第一个字母采用小写。 例如
public class AllTheColorsOfTheRainbow {
    int anIntegerRepresentingColors;
    void changeTheHueOfTheColor(int newHue){
        //method body
    }
    
    //class body
}

7.总结

  • 通过本章的学习,可以对Java语言以及一些基本思想也有了一个总体的认识。
  • 从Java的内存存储到什么地方 到 八大基本数据类型  到 Java作用域,对象作用域  到类(class) 字段和方法 , 到 static关键字 到  Javadoc注释文档 到类名 方法名名称如何起 都有了一定简单的认识

 

 

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章