Java技术与应用,位运算和面向对象编程

来源:互联网 发布:灵娱网络官网 编辑:程序博客网 时间:2024/05/02 02:22
  1. Java的一些基本概念
    1. Java的起源
            Java来自于Sun公司的一个叫Green的项目,其原先的目的是为家用消费电子产品开发一个分布式代码系统,这样我们可以把E-mail发给电冰箱、电视机等家用电器,对它们进行控制,和它们进行信息交流。
            开始,准备采用C++,但C++太复杂,安全性差,最后基于C++开发了一种新的语言Oak(Java的前身),Oak是一种用于网络的精巧而安全的语言,Sun公司曾以此投标一个交互式电视项目,但结果被SGI打败。可怜的Oak几乎无家可归,恰巧这时Mark Ardreesen开发的Mosaic和Netscape启发了Oak项目组成员,他们用Java编 制 了HotJava浏 览器,得到了Sun公司首席执行官Scott McNealy的支持,触发了Java进 军Internet。
            Java的取名也有一则趣闻,有一天,几 位Java成员组的会员正在讨论给这个新的语言取什么名字,当时他们正在咖啡馆喝着Java(爪哇)咖 啡,有一个人灵机一动说就叫Java怎 样,得到了其他人的赞赏,于是,Java这个名字就这样传开了。
    2. 为什么我们要学习Java语言
      1. 简单的
        Java最初是为对家用电器进行集成控制而设计的一种语言,因此它必须简单明了。Java语言的简单性主要体现在三个方面:
        1. Java的风格类似于C++,因而C++程序员初次接触Java语言,就会感到很熟悉。从某种意义上讲,Java语言是C及C++语言的一个变种,因此,C++程序员可以很快地掌握Java编程技术。
        2. Java摒弃了C++中容易引发程序错误的一些特性,如指针、结构、枚举以及内存管理等。
        3. Java提供了丰富的类库,可以帮助我们很方便的开发Java程序。
      2. 面向对象的
        面向对象可以说是Java最重要的特性,所以它支持继承重载多态等面向对象的特性。Java语言的设计是完全面向对象的,它不支持类似C语言那样的面向过程的程序设计技术。
      3. 健壮的
        Java致力于检查程序在编译和运行时的错误。Java也是一种强类型的语言,其类型检查比C++还要严格。类型检查帮助我们检查出许多开发早期出现的错误。Java自己负责内存管理提供了垃圾内存回收机制,有效的避免了C++中最头疼的内存泄漏问题。
      4. 安全的 
        Java的安全性可从两个方面得到保证。
        1. 一方 面,在Java语言里,删除了指针和释放内存等C++功能,避免了非法内存操作。
        2. 另一方面,通过Java的安全体系架构来确保Java代码的安全性。当我们从网上下载Java代码在本地执行时,Java的安全架构能确保恶意的代码不能随意访问我们本地计算机的资源,例如:删除文件,访问本地网络资源等操作都是被禁止的
      5. 解释的
        Java代码是解释执行的,我们使用Java编译器将Java代码编译成字节码,这是一种中间代码,然后由Java解释器解释执行。而C++程序是编译执行的,C++程序代码被编译为本地机器指令,然后执行。
      6. 与平台无关的
        Java作为一种网络语言,其源代码被编译成一种结构中立的中间文件格式。只要有Java运行系统的机器都能执行这种中间代码。Java源程序被编译成一种与机器无关的字节码格式,在Java虚拟机上运行。
      7. 多线程的
        Java语言的一个重要特性就是在语言级支持多线程的程序设计。
        多线程就好像我们做一张桌子,如果你一个人完成这张桌子—就好像单线程,那么你需要先做桌面,做完桌面后,再做4个桌子腿,如果现在有5个人来做桌子—在程序中开辟5个线程,其中1个人做桌面,另外4个人分别做4个桌子腿,那么这两种方式效率的高低,相信大家都能区分出来。
      8. 动态的
              Java的动态特性是其面向对象设计方法的扩展。它允许程序动态地装入运行过程中所需要的类,这是我们采用C++语言进行面向对象程序设计所无法实现的。
              在C++程序设计过程中,每当在类中增加一个实例变量或一个成员函数后, 引用该类的所有子类都必须重新编译,否则将导致程序崩溃。
        Java从以下几个方面采取措施来解决这个问题。
              Java编译器不是将对实例变量和成员函数的引用编译为数值引用,而是将符号引用信息在字节码中保存下来,传递给解释器,再由解释器在完成动态连接类后,将符号引用信息转换为数值偏移量。一个在存储器中生成的对象不在编译过程中决定,而是延迟到运行时由解释器确定。这样,对类中的变量和方法进行更新时就不至于影响现存的代码。
              解释执行字节码时,这种符号信息的查找和转换过程仅在一个新的名字出现时才进行一次,随后代码便可以全速执行。在运行时确定引用的好处是可以使用已被更新的类,而不必担心会影响原有的代码。如果程序连接了网络中另一系统中的某一类,该类的所有者也可以自由地对该类进行更新,而不会使任何引用该类的程序崩溃。
              Java还简化了使用一个升级的或全新协议的方法。如果你的系统运行Java程序时遇到了不知怎样处理的程序,Java能自动下载你所需要的功能程序。
    3. Java跨平台原理剖析
      Java的跨平台是通过Java虚拟机(JVM)来实现的。
      Java应用程序的开发周期包括编译下载解释执行几个部分。
      1. Java源文件的编译过程
        Java编译程序将Java源程序翻译为JVM可执行代码—字节码。
              这一编译过程同C/C++的编译有些不同。当C编译器编译生成一个对象的代码时,该代码是为在某一特定硬件平台运行而产生的。因此,在编译过程中,编译程序通过查表将所有对符号的引用转换为特定的内存偏移量,以保证程序运行。
              Java编译器却不将对变量和方法的引用编译为数值引用,也不确定程序执行过程中的内存布局,而是将这些符号引用信息保留在字节码中,由解释器在运行过程中创建内存布局,然后再通过查表来确定一个方法所在的地址。这样就有效的保证了Java的可移植性和安全性。
      2. Java解释器的执行过程
        运行JVM字节码的工作是由解释器来完成的。
        解释执行过程分三步进行:代码的装入、代码的校验和代码的执行
              装入代码的工作由“类装载器”(class loader)完成。类装载器负责装入运行一个程序需要的所有代码,这也包括程序代码中的类所继承的类和被其调用的类。当类装载器装入一个类时,该类被放在自己的名字空间中。除了通过符号引用自己名字空间以外的类,类之间没有其他办法可以影响其它类。在本台计算机上的所有类都在同一地址空间内,而所有从外部引进的类,都有一个自己独立的名字空间。这使得本地类通过共享相同的名字空间获得较高的运行效率,同时又保证它们与从外部引进的类不会相互影响。当装入了运行程序需要的所有类后,解释器便可确定整个可执行程序的内存布局。解释器为符号引用同特定的地址空间建立对应关系及查询表。通过在这一阶段确定代码的内存布局,Java很好地解决了由超类改变而使子类崩溃的问题,同时也防止了代码对地址的非法访问。
              随后,被装入的代码由字节码校验器进行检查。校验器可发现操作数栈溢出,非法数据类型转换等多种错误。
              通过校验后,代码便开始执行了。
      3. Java字节码的两种执行方式
        1. 即时编译方式:解释器先将字节码编译成机器码,然后再执行该机器码。
        2. 解释执行方式:解释器通过每次解释并执行一小段代码来完成Java字节码程序的所有操作。
          通常采用的是第二种方法。由于JVM规格描述具有足够的灵活性,这使得将字节码翻译为机器代码的工作具有较高的效率。对于那些对运行速度要求较高的应用程序,解释器可将Java字节码即时编译为机器码,从而很好地保证了Java代码的可移植性和高性能。
      4. JVM规格描述
              JVM的设计目标是提供一个基于抽象规格描述的计算机模型,为解释程序开发人员提供很好的灵活性,同时也确保Java代码可在符合该规范的任何系统上运行。JVM对其实现的某些方面给出了具体的定义,特别是对Java可执行代码,即字节码(Bytecode)的格式给出了明确的规格。这一规格包括操作码和操作数的语法和数值、标识符的数值表示方式、以及Java类文件中的Java对象、常量缓冲池在JVM的存储映象。这些定义为JVM解释器开发人员提供了所需的信息和开发环境。Java的设计者希望给开发人员以随心所欲使用Java的自由。
              JVM是为Java字节码定义的一种独立于具体平台的规格描述,是Java平台独立性的基础。
      5. Java程序执行与C/C++程序执行的对比分析
              如果把Java源程序想象成我们的C++源程序,Java源程序编译后生成的字节码就相当于C++源程序编译后的80x86的机器码(二进制程序文件),JVM虚拟机相当于80x86计算机系统,Java解释器相当于80x86CPU。在80x86CPU上运行的是机器码,在Java解释器上运行的是Java字节码。
              Java解释器相当于运行Java字节码的“CPU”,但该“CPU”不是通过硬件实现的,而是用软件实现的。Java解释器实际上就是特定的平台下的一个应用程序。只要实现了特定平台下的解释器程序,Java字节码就能通过解释器程序在该平台下运行,这是Java跨平台的根本。当前,并不是在所有的平台下都有相应Java解释器程序,这也是Java并不能在所有的平台下都能运行的原因,它只能在已实现了Java解释器程序的平台下运行。
      6. Java开发工具包(JDK)的下载
        http://java.sun.com
  2. Java环境变量的配置
    在 我的电脑->属性->高级->环境变量,在弹出的对话框里 对系统变量 新建系统变量。

    点击确定。

    可以在开始,运行,输入cmd,再输入javac(编译.java后缀名的Java源文件),java(用于运行编译好的.class后缀名的文件),这2个命令测试下。如果列出一大堆的命令参数列表,说明环境变量设置成功。
  3. 初学者常犯的问题
    每个Java代码源文件指定要有一个类,如果这个类申明为public则必须类名与文件前缀名相同(当然,作为一个习惯,一个文件就写一个类),显然,一个文件里只能有一个public类。
    jar用于打包:
        jar cvf 新件包文件名 类名 类名
    例如:
        jar cvf sample Hello.class HelloWorld.class
        则表示在当前路径把hello.class和HelloWorld.class打成sample的包。

        将eXeForJava目录下的所有文件打包成sample包(当前路径必须存在eXeForJava目录)
        jar cvf sample eXeForJava
  4. Java语言的基本数据类型
    1. 变量(8种变量类型)

      byte b;
      short s;
      int i;
      long l;
      float f;
      double d;
      boolean bool;
      char c = 'W';

      Java类型检查是很严格的。

      byte b = 3;
      b = b * 3; //This will cause an error,for the result will be an interger number.
      b = (byte) (b * 3);  //This one will be ok.
      System.out.println(b);


      关于if(1),这样写是错误的,应该这样写:

      if(true)
      {
      }

    2. 数组
      定义方法:

      数组类型名[] 数组名 = new 数组类型名[];


      数组的初始化:

      int [] num=new int[]{1,2,3}; //ok
      int [] num=new int[3]{1,2,3}; //error;
      int [] num;
      num=new int[3];
      num[0]=1;
      num[1]=12;
      num[2]=32;
      System.out.println(num[0]);
      System.out.println(num[1]);
      System.out.println(num[2]);


      多维数组:

        /*int [][] num;
        num=new int[3][4];
        num[0][1]=12;
        num[2][3]=34;*/  

        /*int [][] num;
        num=new int[3][];
        num[0]=new int[5];
        num[1]=new int[3];
        num[2]=new int[2];  
        num[0][4]=45;
        num[1][2]=34;
        num[2][1]=21;
        System.out.println(num[0][4]);
        System.out.println(num[1][2]);
        System.out.println(num[2][1]);
        System.out.println(num[2][2]);*/  

        //int [][] num=new int[][]{1,2,3,4,5,5};  //error
        //int [][] num=new int[][]{{1,2,3},{4,5,5}}; //ok
        //int [][] num=new int[2][]{{1,2,3},{4,5,5}}; //error
        //int [][] num={{1,2,3},{4,5,6}};  //ok 
       
        /*int [][] num={{1,2,3},{4,5},{6}};
        System.out.println(num[0][2]);
        System.out.println(num[1][1]);
        System.out.println(num[2][0]);*/


      关于i++与++i:

        /*int i=3;
        //System.out.println(i++);
        System.out.println(++i);*/  

        /*int i=3;
        //int count=(i++)+(i++)+(i++);    //4 + 4 + 4 = 12
        int count=(++i)+(++i)+(++i);       //4 + 5 + 6 = 15
        System.out.println(i);
        System.out.println(count);*/

    3. Java的语句。

        if()
        {
        }
        while(true)
        {
        }
        do
        {
        }while(true);

    4. 工具使用
      最好的代码编辑器:EditPlus v2.21
      JDK 1.5 : http://java.sun.com
  • 计算机中数据的表示方法
          计算机是一种电子设备,由复杂的电子元器件组合而成,一个电子元器件有带电和不带电两种状态,通常我们将带电状态表示为数值1,不带电状态表示为数值0,多个这样的元器件的组合可以表示更多状态,也就是可以表示更多的数据,如000表示0,001表示1,010表示2,011表示3,依此类推,111表示7,一个元器件可表示一位(bit)数据,这种表示数据的方式就叫二进制。
          在实际的电子设备中,我们将8个这样的元器件形成一个单元,这样的单元叫一个字节(byte),一个字节能表示多少个数呢?表示数值的范围是0-255
          一个字节由8个二进位组成,其中最右边的一位称为“最低有效位”或“最低位”,最左边的一位称为“最高有效位”或“最高位”。每一个二进位的值是0或1。

          二进制计数的缺点:书写太长,容易出错,一般计算机的数据位数都是4的整数倍,所以,在计算机里通常采用16进制计数法。用数字可以表示各种信息,计算机里只有数值,当你在内存中看到一个数值时,这个数值可能代表各种意义,生活中的数值也可以代表其他意义,如1234可以代表密码,存款额,电报信息,根据上下线索,我们就能够知道这数值代表的意义。
  • 原码
          
    将最高位作为符号位(以0代表正,1代表负),其余各位代表数值本身的绝对值(以二进制表示)。
                为了简单起见,我们用1个字节来表示一个整数。
                +7的原码为: 00000111
                 -7的原码为: 10000111
        问题:
               +0的原码为:             00000000
                -0的原码为:             10000000
  • 反码
          一个数如果为正,则它的反码与原码相同;一个数如果为负,则符号位为1,其余各位是对原码取反。
                为了简单起见,我们用1个字节来表示一个整数。
                +7的反码为: 00000111
                 -7的反码为: 11111000
        问题:
               +0的反码为:             00000000
                -0的反码为:             11111111
  • 补码
        利用溢出,我们可以将减法变成加法。
        对于十进制数,如果从9得到结果5,可以用减法:
             9-4=5
          因为4+6=10,我们将6作为4的补数,将上式的减法改写为加法:
             9+6=15
          去掉高位1(也就是减去10),得到结果5。

          对于16进制数,如果从C得到结果5,可以用减法:
             C-7=5
          因为7+9=16,我们将9作为7的补数,将上式的减法改写为加法:
             C+9=15
          去掉高位1(也就是减去16),得到结果5。

          在计算机中,如果我们用1个字节表示一个数,一个字节有8位,超过8位就进1,在内存中情况为:
               1 00000000
        进位1被丢弃。

    一个数如果为正,则它的原码、反码、补码相同;一个数如果为负,则符号位为1,其余各位是对原码取反,然后整个数加1。
                为了简单起见,我们用1个字节来表示一个整数。
                +7的补码为: 00000111
                 -7的补码为:第一步:11111000 (符号位为,其余各位取反)
                                   第二步:11111001 (整个数加1)
               +0的补码:00000000;
                -0的补码:11111111;(第一步)
                              100000000;(第二步)

    已知一个负数的补码,将其转换为十进制数,步骤:
          1、先对各位取反;
          2、将其转换为十进制数;
          3、加上负号,再减去1。
          例如:
          11111010,最高位为1,是负数,先对各位取反得00000101,转换为十进制数得5,加上负号得-5,再减1得-6。
  • 位运算符
    为了方便对二进制位进行操作,Java给我们提供了四个二进制位操作符:
    &          按位
    |           按位
    ^          按位异或
    ~          按位取反
  • 按位
                 一个房间里有两个开关控制房间的灯的明暗。当两个开关同时处于打开状态时,灯才能亮。
         开关1                   开关2                         灯的状态
           关                         关                              暗
          开                          关                              暗
          关                          开                              暗
          开                          开                              亮
    结论:按位与,只有壹(1)壹(1)为1。
  • 按位
                一个房间里有两个开关控制房间的灯的明暗。当任何一个开关处于打开状态时,灯就能亮。
        开关1                     开关2                     灯的状态
           关                         关                              暗
          开                          关                              亮
          关                          开                              亮
          开                          开                              亮
    结论:按位或,只有零(0)零(0)为0。
  • 按位异或
                一个房间里有两个开关控制房间的灯的明暗。当两个开关处于不同状态时,灯就能亮。
       开关1                    开关2                       灯的状态
          关                          关                              暗
          开                          关                              亮
          关                          开                              亮
          开                          开                              暗
    结论:按位异或,只有零(0)壹(1)或壹(1)零(0)为1。
  • 按位取反
    结论:对二进制数按位取反,即0变成1,1变成0。
  • Java中有三个移位运算符
    左移:<<              (相当于 乘以2
    带符号右移:>>     (相当于 除以2

    无符号右移:>>>
      数            x                   x<<2                 x>>2              x>>>2
     17      00010001    00 01000100      00000100 01     00000100 01
    -17     11101111     11 10111100      11111011 11     00111011 11
    练习:将一个整数110从右端开始的4~7位变为0。
面向对象编程
  1. 面向对象编程概述
    • 简单的说,面向对象编程(Object Oriented Programming,简称OOP)描述的是对象之间的相互作用。
    • 面向对象编程与面向过程编程的区别:
            过程化程序设计确定算法,再确定数据结构;
            面向对象编程先确定数据结构,再确定运算。
            面向过程编程的程序员,习惯于建立数据结构存放数据并定义方法(函数)来操作数据;
            面向对象编程的程序员则构造一个对象模型,将数据与方法组织在一起。
  2. 对象  对象的状态  对象的行为
    • 我们可以把现实世界的事物抽象成对象。
    • 对象一般都有两个特征:状态(state)和行为(behavior)。
    • 软件的对象概念是由现实世界对象抽象而来 。
      把现实世界对象的状态保存在软件对象的变量中;现实世界对象的行为通过软件对象的方法(函数)来实现。
  3. 类和对象
    • 把相似的对象划归成一个
    • 在软件中,类,就是一个模板,它定义了通用于一个特定种类的所有对象的状态(变量)和行为(方法)。
    • 类是创建对象的模板,对象是类的实例
  4. 面向对象程序设计
    • 从程序设计的角度看,类是面向对象程序中最基本的程序单元。类实质上定义的是一种数据类型,这种数据类型就是对象类型 。所以我们可以使用类名称来声明对象变量。
    • 声明对象变量之后,还不能使用对象。必须用运算符new创建对象实体之后,才能使用对象。
  5. 面向对象编程的难点
    • 掌握面向对象的困难之处在于思路的转换。
                  
          我们通常习惯于考虑解决问题的方法,而不是考虑将问题抽象成对象再去解决它
  6. 一个简单的例子
    • 编写一个驾驶汽车的方法
      面向过程的程序设计:
              编写一个方法,void drivecar();
      面向对象的程序设计:
              将一辆汽车看成一个对象,将所有汽车对象的共性抽取出来,设计一个类Car,类中有一个方法void drive(),用Car这个类实例化一个具体的对象car,调用:car.drive()。
  7. 类的构造方法
    • 构造方法的名字和类名相同,并且没有返回值。
    • 构造方法主要用于为类的对象定义初始化状态。
    • 我们不能直接调用构造方法,必须通过new关键字来自动调用,从而创建类的实例。
    • Java的类都要求有构造方法,如果没有定义构造方法,Java编译器会为我们提供一个缺省的构造方法,也就是不带参数的构造方法。(javap来反编译可以得到)
  8. new关键字的作用
    • 为对象分配内存空间。
    • 引起对象构造方法的调用。
    • 为对象返回一个引用。
  9. 缺省构造方法
    • 当我们用缺省的构造方法初始化对象时,系统用默认值初始化对象的成员变量。
    • 各种数据类型的默认值为:
      数值型       0
      boolean   false
      char       ‘/0’
      对象         null
  10. 方法的重载(overload)
    • 重载构成的条件:方法的名称相同,但参数类型或参数个数不同,才能构成方法的重载。
  11. 特殊变量this
    • this变量代表对象本身
    • 当类中有两个同名变量,一个属于类(类的成员变量),而另一个属于某个特定的方法(方法中的局部变量),使用this区分成员变量和局部变量。
    • 使用this简化构造函数的调用。
    • 关于实例方法和实例数据成员的进一步说明
           一个类所有的实例(对象)调用的成员方法在内存中只有一份拷贝,尽管在内存中可能有多个对象,而数据成员在类的每个对象所在内存中都存在着一份拷贝。this变量允许相同的实例方法为不同的对象工作。每当调用一个实例方法时,this变量将被设置成引用该实例方法的特定的类对象。方法的代码接着会与this所代表的对象的特定数据建立关联。
  12. 关键字static
    • 静态方法和静态变量是属于某一个类,而不属于类的对象。
    • 静态方法和静态变量的引用直接通过类名引用。
    • 在静态方法中不能调用非静态的方法和引用非静态的成员变量。反之,则可以。
    • 可以用类的对象obj去调用静态的方法method(),如:obj.method()。
    • 实例方法是必须实例话才可以调用的方法,实例名.方法名()
  13. 常量的定义
    • 使用关键字final定义常量,例如:
          final double PI=3.1415926;
    • 作为一种约定,在定义常量时,通常采用大写形式。
    • final常量可以在声明的同时赋初值,也可以在构造函数中赋初值。
    • 为了节省内存,我们通常将常量声明为静态的(static)。
  14. 类的继承
    • 理解继承是理解面向对象程序设计的关键。
    • 在Java中,通过关键字extends继承一个已有的类,被继承的类称为父类(超类,基类),新的类称为子类(派生类)。
    • 在Java中,不允许多继承。
  15. 方法的覆盖(override)
    • 在子类中定义一个与父类同名、返回类型、参数类型均相同一个方法,称为方法的覆盖。
    • 覆盖发生在子类与父类之间。
  16. 特殊变量super
    • 特殊变量super,提供了对父类的访问。
    • 可以使用super访问父类被子类隐藏的变量或覆盖的方法。
    • 每个子类构造方法的第一条语句,都是隐含地调用super(),如果父类没有这种形式的构造函数,那么在编译的时候就会报错。
  17. 多态性
    • 通过覆盖父类的方法来实现,在运行时根据传递的对象引用,来调用相应的方法。
  18. 面向对象的程序设计
    • 问题:求一个长方形的周长和面积。
      以面向过程的程序设计方式思考:
           1、确定长方形周长和面积的算法。
           2、编写两个方法(函数)分别计算长方形的周长和面积。
           3、求周长的方法(函数)和求面积的方法(函数)需要两个参数,分别是长方形的长和宽。
    • 面向过程的程序设计代码:

      class Rectangle
      {
           static int perimeter(int length,int width)
           {
                  return 2*(length+width);
            }
            static int area(int length,int width)
            {
                  return length*width;
            }
            public static void main(String[] args)
            {
                  System.out.println("perimeter = “ + Rectangle.perimeter(5,4));
                  System.out.println("area = “ + Rectangle.area(5,4));
            }
      }

    • 问题:求一个长方形的周长和面积。
      以面向对象的程序设计方式思考:
           1、一个长方形可以看成一个长方形对象。
           2、一个长方形对象有两个状态(长和宽)和两个行为(求周长和求面积)。
           3、将所有长方形的共性抽取出来,设计一个长方形类。
           4、通过长方形对象的行为,就可以求出某个具体的长方形对象的周长和面积。
 
原创粉丝点击