OOP

  • 对象有三个要素

    • behavior

      • 接口是怎样的,有什么方法/field可以用?
    • state
      • 调用方法的时候,对象会有什么反应?
      • 只有通过调用方法才能改变一个对象的state
    • identity
      • 对象之间如何区分?
  • 类的三大关系
    • dependence

      • uses-a
      • 在方法里用到的类(方法的local variable)
      • 应当尽可能地少
    • Aggregation
      • has-a
      • 自己本身有的类(自己的field)
    • Inheritance
      • is-a
      • general v.s. specialized

Java自带类的入门

  • 只封装了functionality的Math
  • Date
  • GregorianCalander

Java OO初步 - 以Date为例

  • Date的API文档
  • Date是用来表示某一个时刻而不是某一个现实世界的时刻的(设计的初衷是UTC时间,但是又没有遵守一些复杂的历法规则)
  • 用来表示现实世界时间的另有一些其他类,比如GregorianCalander(常用的公历),这样方便不同的locale用不同的历法,它们都继承Calendar(相对于太general的Date而言,一个Calendar加上一堆子类确实是更好的设计……)
  • derefernce一个null会在runtime抛出error
  • 所有的Java对象都被放置在
  • 和JS类似,Java对象都是引用,=只会得到shallow copy,需要deep copy的时候需要调用Object均带有的clone()

Java OO初步 - 以GregorianCalander为例

  • API
  • 月份从0数起,为了防止出错以及减轻对底层实现的依赖,传月份的时候最好使用Calendar这个虚类的常量,比如Calendar.DECEMBER,星期的名字也是一样
  • get和set需要将相关的field通过参数传入而不是直接调用不同名字的方法,相关的field用Calendar的常量表示 e.g. deadline.set(Calendar.YEAR, 2014)
  • add可以修改时间,负数的增量表示倒退
  • setTimegetTime可以用来完成Calander和Date之间的转换
  • 有一个DateFormatSymbols用来获取当前locale关于日期的一些名字,比如星期一叫什么(Monday(英文)?星期一(中文)?)

自定义类

  • main函数需要寄存在一个类里
  • 一个文件里只能有一个public类,其他类可以有多个。文件名必须和自己的public类的名字相同
  • Java编译器自带类似于make的功能,会查找依赖,如果没有找到.class会自动找对应的.java并编译,或者如果.java修改过了也会重新编译
  • 构造函数要且必须要用new来调用,直接用会在编译时报错
  • 虽然方法内声明的变量不存在shadow,但是方法参数的名字和类自带field的名字可以存在shadow(此时自带的field需要加上this),不过参数名不能再用来声明新的local变量
  • this和JS里的用法一样,后面跟点
  • Java里所有类的实现都和类的声明写在一块儿,长得类似C++的inline声明,只不过在Java里决定是否inline是编译器的活
  • 在方法内返回类的field时,如果它是对象,Java不会做一个deep copy再返回,所以实际上返回的是这个对象的引用,会破坏封装。为此需要返回它的.clone()的返回值

Static

  • Java里类中的常量使用也final声明,和C++不同的是,它在整个构造函数里都可以被修改(C++里常量一定要通过member initializer这种诡异的方法去设置,到函数体里就不能动了),出了构造函数才不能动
  • Java标准库里那些标了native的函数是可以绕过Java自己的语法限制的,比如一个API里说是final的field还可以用某些方法修改(因为native的函数不是用Java实现的(通常是C/C++),所以可以绕过这个限制)
  • Java的static方法和C++一样,没有this,不能调用非static的方法,也不能使用非static的field。同样地,static方法不一定只能用类名调用,也可以随意用一个这个类的对象调用,虽然这种做法比较confusing所以不推荐
  • 为一个方法标明static大约有两种情形
    • 这个方法不改变对象的状态,所以不需要修改nonstatic filed
    • 这个方法只需要访问static的field
  • 作者吐槽了一下static这个名字的三重含义2333 (C里面可以指只初始化一次的变量(最符合static字面意思的意义),或者只有当前文件能访问的变量。到了C++又加上了一个类里共有的成员的意思,也是java唯一沿用的含义)
  • 在Java里,访问权限的设置和C++类似,同一个类对象可以访问彼此的private成员,子类不能访问父类的private成员,但是Java的继承只有public一种,没有那堆复杂无比的规则
  • 顺带介绍了一下factory模式
  • main函数也必须是static的。注意每个类都可以有main函数,这样方便做单元测试。在运行的时候,只会用入口的.class里的main函数,其他类的main函数会被无视。这样的话,如果要跑一个叫ClassA的类的单元测试,可以在这个类里写个main函数,然后执行

    $ java ClassA

    如果要跑用了多个类,包括ClassA的程序,入口写在Runner.java里,可以跑

    $ java Runner

    这样ClassA的main函数就会被无视。注意这里可能还需要加上classpath说明怎么找到ClassA和其他类。另外,private类也可以有main函数,只要声明是

    public static void main(String[] args)

    就行了。

参数

  • Java和JS一样,一切都是call-by-value,函数参数传进来的引用内容可以改,引用指向的对象不能改,原始类型不是引用就是直接copy再传进来了,怎么动都没事

对象的构造

  • Java和C++一样,用signature实现函数重载
  • 所有field都会有默认初识值(数字是0, boolean是false,对象是null)。注意是field才会有默认值,不初始化也能用,local变量是没有的,不初始化就不能用。
  • 和C++一样,没有构造函数的时候会提供一个默认构造函数
  • 在Java里用来给field直接赋值的构造函数参数名的几种convention是
    • 用首字母,小写
    • 开头加a,驼峰
    • 直接同名,这时候会产生shadow,所以在指定field的时候要加this
    • 没有C++那种加下划线的convention
  • Java里构造函数居然可以互相调用 =口= 用法是

    this(...)

    然后就会根据传进去的参数匹配对应的构造函数。这个调用一定要写在构造函数的第一句。这样一来如果很多构造函数都有相同的代码,就可以抽象到某一个构造函数里,然后大家一起调用它。

  • 可以在类声明里直接给field写上初始值,这个初始化可以在构造函数前执行完,所以如果有一些field需要一个很多构造函数都会给它的初始值,可以在类声明里面写,就不用在N个构造函数里都写了。注意这个初始值还可以是某个函数的返回值,不一定需要是literal。
  • 如果光用一个函数返回值还不足以初始化,那么还可以用上initialization block,里面就可以写语句了,参见Initializing Fields (The Java™ Tutorials > Learning the Java Language > Classes and Objects)
  • initialization block和field的声明不一定有先后,可以夹杂起来的,而且没有声明的field还是不能初始化的,这里有一堆复杂的规定(复杂到早期的java编译器自己都有些不符合speciation的地方),一般来说建议把所有声明都写完再写initialization block
  • 初始化的顺序大约是
    1. 先赋默认值
    2. field initializer和initialization block按照在代码里出现的顺序执行
    3. 如果这个构造函数还调用了另一个构造函数(人家要写在第一行),调用它
    4. 最后执行这个构造函数的函数体
  • static field还可以通过一个static initialization block初始化,只要在花括号前写上static就行。
  • static initialization block会在这个类第一次load的时候执行,所以如果你在里面写上输出hello world的语句,你就可以在没有main函数的情况下输出hello world = =虽然运行时会会在执行完static initialization block里的语句后报错main函数没有定义。如果你还想逃脱这个报错,只要加上System.exit(0)就好(这样玩真的有意思吗喂!!)

对象的析构

  • Java里没有析构函数,但是可以有一个叫finalize的方法,在每次GC清理对象的时候会执行。不过这个方法执行的时机是不确定的,所以不能依赖它回收资源。最好的方法就是直接在任何申请了资源的函数里及时回收。
  • Java的GC和JS差不多,用的是Mark and Sweep,所以无法确定finalize何时被调用

package

  • java的类可以放在package里分发,package的命名方式通常会按照所属机构的域名倒着写,所以你会经常看到叫com.xxx.yyy的pacakage,制作这个package的人所在的机构的网站域名就会是xxx.com
  • 嵌套的package没有包含关系,java.util和java.util.jar里的类是不一样的。
  • 调用一个package的类可以每次指明它都写上全名,也可以先import它进来就不用写前面的package的名字了。import一定要写在文件开头。
  • import可以用 * 来获得一个package的所有类,eclipse提供将 * 展开成文件里使用过的类名的功能。注意 * 只能用来指一个package的所有类,不可以放在上一级指多个package
  • bytecode里会把所有类名展开全,java编译器和C++编译器的区别注意在于C++的编译器不会看被#inlcude的文件的内容,而java会看被import的类的代码
  • import还可以用来获得一个类的public static的方法或者field,这时需要写类似import static package.class.method的语句(注意import后跟static)。如果想import全部static成员,用 * 就行。
  • 如果想将一个新的类加入现存的package里,可以在这个类的声明前写上

    package packageName

    在指定的package里将这个类塞进去。如果不写,这个类就会放进default package里

  • 放在package里的类编译得到的bytecode需要按照package的名字创建好目录结构(每个点分割的元素加一层文件夹),放在项目根目录下。这样JVM就知道去哪里找这个类的bytecode(这里假设根目录会加进classpath里)。
  • 这个package的查找是在运行时进行的,编译器不会去检查,JVM才会。
  • 一个类里可以引用同一个package的其他类和其他package的public类。注意类名前不写modifier默认是private,但是类的field前不写默认是public(和C++相反)。很多人会忘记写上private,于是同一个package的所有类都可以随便获得这个field了,Java标准库里的java.awt.Window的warningString就是这样一个field呵呵呵呵,而且这个bug一直没被解决(作者自黑了一把:我们在core java第八版都说过这个bug了他们还没改,显然java标准库的维护者们都不看我们的书呢2333)
  • 对于存在这种笔误的field,你可以通过设置文件目录+使用package来偷偷修改掉这个field,比如利用前面提到的标准库里的bug,你可以突破封装,修改标准库里的warningString 23333 不过从JDK 1.2开始所有java.开头的package都被seal起来不能用package改了,算是亡羊补牢。

class path

  • .jar其实也是一种ZIP格式,所以能够打开ZIP的软件也能用来打开或者解压.jar。里面通常是一个按照package的名字构造好的目录结构,里面按规则放着.class和其他文件,这样可以省空间。
  • JVM寻找类的时候会从class path里列出来的目录开始按package的名字结构去找。class path可以在编译指令里用-classpath(缩写-cp)设置,也可以在环境变量CLASS_PATH里设置一个通用的列表

    • 注意当运行指令里没有-classpath的时候,默认的class path包括运行时的工作目录。但是如果有设class path,工作目录是不会默认出现在里面的,此时有两种解决方案

      1. 在class path里直接加上工作目录,比如在Unix-like系统下

        $ java -cp .:dir1:dir2:dir3:dir4...  package1.package2.className

        开头的点就表示工作目录,Unix-like系统下用冒号分割(在win下用分号)

      2. 在环境变量CLASS_PATH里直接加上那个点,就不用每次写编译指令都设进去了
    • 注意随便设环境变量不是好事,而且一旦指明了CLASS_PATH又不在里面加上点,每次跑的时候class path总会缺了当前目录——苹果的QuickTime installer曾经干的好事
    • 编译器(javac)总是会检查当前目录的,不会检查的是运行时(java)
    • 注意class path里的wildcard用法和linux下的不同,* 不能随便乱用,参见 Java SE Documentation: Setting the class path
  • runtime库里的文件和jar会自动加进class path
  • JVM的查找顺序是
    1. 在runtime库里查找(比如jre/lib)
    2. 在class path里嵌套的package里找
    3. 从当前目录开始查找
    4. 从class path里指明的jar里查找
  • Java编译器的查找
    • 编译器会参考所有import语句来搜索
    • 编译器会以class path里指明的每一个目录为起点,展开import语句去搜索
    • 编译器找到更新过的代码也会自动重新编译
    • 当找到多个重名的类的时候会报编译时错误
    • 因为一个文件只能有一个public类,而且文件名还要和类名一样,所以编译器查找文件的时候会方便很多。但是如果在同一个package里,一个类是可以import同一package的其他private类的,这个时候要靠编译器去把这个package里的文件都看一遍才行。
    • 所以Java编译器的查找虽然不那么需要在class path里写明一堆目录,但是慢很多

注释

  • Java有一个很吊的工具,叫做javadoc,写法参见这里这里。只要按照约定好的方式去写注释,用javadoc跑一遍就能自动生成HTML文档。JDK6的官方API文档和hadoop的官方API文档都是用这个生成的。
  • JDK6生成的样式长得太蛋疼了,自己魔改了一个css在这里。好在javadoc生成的文档会共用目录下的一个stylesheet.css,通过修改它就可以影响这一套文档的外观。

Before

After

一些tips

  • 当一个类里有太多个基本类型的field的时候,说明可能有一些field本身就可以组成一个类然后再加进来了。

http://www.cnblogs.com/joyeecheung/p/3859430.html

java OOP及相关基础知识汇总(转)的更多相关文章

  1. JAVA面试题相关基础知识

        1.面向对象的特征有哪些方面 ①抽象: 抽象就是忽略一个主题中与当前目标无关的那些方面,以便更充分地注意与当前目标有关的方面.抽象并不打算了解全部问题,而只是选择其中的一部分,暂时不用部分细节 ...

  2. 关于GC(中):Java垃圾回收相关基础知识

    Java内存模型 (图源: 深入理解JVM-内存模型(jmm)和GC) 区域名 英文名 访问权限 作用 备注 程序计数器 Program Counter Register 线程隔离 标记待取的下一条执 ...

  3. 沉淀,再出发:Java基础知识汇总

    沉淀,再出发:Java基础知识汇总 一.前言 不管走得多远,基础知识是最重要的,这些知识就是建造一座座高楼大厦的基石和钢筋水泥.对于Java这门包含了编程方方面面的语言,有着太多的基础知识了,从最初的 ...

  4. JAVA相关基础知识

    JAVA相关基础知识 1.面向对象的特征有哪些方面 1.抽象: 抽象就是忽略一个主题中与当前目标无关的那些方面,以便更充分地注意与当前目标有关的方面.抽象并不打算了解全部问题,而只是选择其中的一部分, ...

  5. 【RAC】RAC相关基础知识

    [RAC]RAC相关基础知识 1.CRS简介    从Oracle 10G开始,oracle引进一套完整的集群管理解决方案—-Cluster-Ready Services,它包括集群连通性.消息和锁. ...

  6. jquery基础知识汇总

    jquery基础知识汇总 一.简介 定义 jQuery创始人是美国John Resig,是优秀的Javascript框架: jQuery是一个轻量级.快速简洁的javaScript库.源码戳这 jQu ...

  7. iOS蓝牙开发(二)蓝牙相关基础知识

    原文链接: http://liuyanwei.jumppo.com/2015/07/17/ios-BLE-1.html iOS蓝牙开发(一)蓝牙相关基础知识: 蓝牙常见名称和缩写 MFI ====== ...

  8. 深入理解mysql之BDB系列(1)---BDB相关基础知识

        深入理解mysql之BDB系列(1) ---BDB相关基础知识 作者:杨万富   一:BDB体系结构 1.1.BDB体系结构 BDB总体的体系结构如图1.1所看到的,包括五个子系统(见图1.1 ...

  9. 《Java核心技术·卷Ⅰ:基础知识(原版10》学习笔记 第5章 继承

    <Java核心技术·卷Ⅰ:基础知识(原版10>学习笔记 第5章 继承 目录 <Java核心技术·卷Ⅰ:基础知识(原版10>学习笔记 第5章 继承 5.1 类.超类和子类 5.1 ...

随机推荐

  1. Java --CountDownLatch简介

    CountDownLatch 1.类介绍 一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待.用给定的计数 初始化 CountDownLatch.由于调用了 coun ...

  2. 2个NASM开发环境下载以及30篇教程(lostspeed)

    http://download.csdn.net/detail/lostspeed/8958175http://download.csdn.net/detail/lostspeed/8954263 h ...

  3. Windows Store Javascript项目使用高德地图、谷歌地图、百度地图API

    原文 Windows Store Javascript项目使用高德地图.谷歌地图.百度地图API 在Win8 Store 项目中可以使用的地图主要有微软的Bing Map,目前高德地图sdk也支持Wi ...

  4. MUI 列表页面绑定接口数据

    1.我们先看效果 2.功能分析 主要分为3步 数据初始化 下拉刷新 上拉加载 接口数据示例: { "List": [ { "Id": 9, "Orde ...

  5. Convert SVG to PNG in Python - Stack Overflow

    Convert SVG to PNG in Python - Stack Overflow Convert SVG to PNG in Python

  6. struts2之高危远程代码执行漏洞,可造成服务器被入侵,下载最新版本进行修复

          Struts2 被发现存在新的高危远程代码执行漏洞,可造成服务器被入侵,只要是Struts2版本 低于 2.3.14.3 全部存在此漏洞.目前官方已经发布了最新的版本进行修复.请将stru ...

  7. 【AC大牛陈鸿的ACM总结贴】【ID AekdyCoin】人家当初也一样是菜鸟

    acm总结帖_By AekdyCoin 各路大牛都在中国大陆的5个赛区结束以后纷纷发出了退役帖,总结帖,或功德圆满,或死不瞑目,而这也许又会造就明年的各种"炸尸"风波.为了考虑在发 ...

  8. C++中实现 time_t, tm 相互转换

    time_t -> tm: localtime tm -> time_t: mktime time_t curTime; time(&curTime); dwCurTime = c ...

  9. QT的动态翻译功能,可能依赖于消息(事件)机制

    QTranslator translator; bool b = translator.load(QString(":/qm/lang_en"));以后,无论使用QObject的t ...

  10. Spring MVC 学习笔记 json格式的输入和输出

    Spring mvc处理json需要使用jackson的类库,因此为支持json格式的输入输出需要先修改pom.xml增加jackson包的引用 <!-- json --> <dep ...