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可以修改时间,负数的增量表示倒退
  • setTime和getTime可以用来完成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面试高频问题】Java数据结构和算法基础知识汇总

    文章目录 Java数据结构和算法基础知识 一.Java数据结构 1. 线性结构:数组.队列.链表和栈 1.1 数组(Array) 1.2 稀疏数组 1.3 队列(Queue) 1.4 链表(Linke ...

  2. JAVA面向对象:相关基础知识(带包编译--权限修饰符--内部类)

    目录 1.带包编译 2.权限修饰符 3.内部类 1.带包编译 解决使用notepad++ 等文本编辑器编写的java类中如果需要 package 的解决方案: 手动式:手动建包,.java文件放在包外 ...

  3. Java相关基础知识小总结

    引言:这是本人学习java过程总结一些基础知识和简单案例 Java开发工具包:安装JDK JDK目录介绍: 1.JDK/bin:存放许多命令,如:javac.exe(负责编译)和 java.exe(负 ...

  4. python基础知识资料-学习Python列表的基础知识汇总

    千里之行,始于足下.要练成一双洞悉一切的眼睛,还是得先把基本功扎扎实实地学好.今天,本喵带大家仔细温习一下Python的列表.温故而知新,不亦说乎. 当然,温习的同时也要发散思考,因为有些看似无关紧要 ...

  5. 学习笔记:Java 并发编程①_基础知识入门

    若文章内容或图片失效,请留言反馈. 部分素材来自网络,若不小心影响到您的利益,请联系博主删除. 视频链接:https://www.bilibili.com/video/av81461839 视频下载: ...

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

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

  7. 脑科学与脑电基础知识汇总

    点击上面"脑机接口社区"关注我们 更多技术干货第一时间送达 脑科学与脑电基础知识汇总 该部分汇总了社区分享的部分脑科学.EEG.fNIRS.BCI.人机交互等相关知识. 脑电与情绪 ...

  8. Java 必看的 Spring 知识汇总

    转载自 Java 必看的 Spring 知识汇总 Spring框架是由于软件开发的复杂性而创建的.Spring使用的是基本的JavaBean来完成以前只可能由EJB完成的事情.然而,Spring的用途 ...

  9. Serdes基础知识汇总

    Serdes基础知识汇总 从知乎https://zhuanlan.zhihu.com/p/423321485转载 在开始了解高速接口的时候,必然会涉及到SerDes.serdes的知识点实际上非常多, ...

最新文章

  1. JavaScript实现shortestCommonSupersequence最短公共超序列算法(附完整源码)
  2. 理解JavaScript继承(二)
  3. 《Android 应用测试指南》——第2章,第2.4节包浏览器
  4. iOS 11.3 显示:Apple ID 或将实现微信式扫码登陆
  5. 全球唯一顶级车展来袭,云徙科技成为造车新势力?
  6. TiDB错误码与故障排除
  7. 2022年全新USDT支付系统源码+支持自动监控回调
  8. 计算机专业英语问卷调查,关于英语调查问卷的总结
  9. Unity特效制作规范
  10. 7 21 第一次团队赛——————写给队友
  11. 期货与期权的主要区别与联系?
  12. java后端必会【基础知识点】
  13. android 设置打印级别
  14. python 画图设置中文字体
  15. 怎样使用Outlook连接Hotmail
  16. 微信小程序招聘管理系统+后台管理系统
  17. 【MySQL】逻辑库与数据表相关操作
  18. C++使用winhttp以POST/GET方法实现报文转发与接收
  19. 多元线性回归的基础理解
  20. PyQt5 实现矩阵计算器

热门文章

  1. 接口加密了该怎么测?
  2. 辽宁工业大学计算机复试经验,辽宁工业大学车辆工程考研经验
  3. ig 焊接机器人_发那科机器人焊接应用的IO配置(总线型)
  4. python开发游戏脚本_Python开发游戏开服脚本
  5. 总结4月13日密室逃脱后至今复习的内容(夯实基础,构建知识脉络)
  6. preferredsize JAVA_Java JScrollPane.getPreferredSize方法代码示例
  7. QTCreator快捷键
  8. 19复变函数的积分(五)
  9. mysql 命令大小写_MySQL连接方式及大小写问题
  10. LightGBM图解理论+视频+安装方法+python代码