第一章 对象导论

“我们之所以将自然界分解,组织成各种概念,并按其含义分类,主要是因为我们是整个口语交流社会共同遵守的协定的参与者,这个协定以语言的形式固定下来…除非赞成这个协定中规定的有关语言信息的组织和分类,否则我们根本无法交。”

-----Benjamin Lee Whorf

1.抽象过程

所有的编程语言都提供抽象机制,人们所能解决的问题的复杂性直接取决于抽象的类型和质量。

  • 万物皆为对象
  • 程序是对象的集合,他们通过发送消息来告知彼此所要的
  • 每个对象都有自己的由其他对象所构成的存储
  • 每个对象都拥有其类型
  • 某一特定类型的所有对象都可以接收同样的消息

2.每个对象都有一个接口

抽象数据类型的运行方式与内置(built-in)类型几乎完全一致:你可以创建某一类型的变量,然后操作这些变量。

每个类的成员或元素都具有某个特性。

Light lt = new Light();
lt.on();

接口确定了对某一个特定对象所能发出的请求。

在UML建模语言中,每个类都用一个方框表示,类名在方框的顶部,任何数据成员都在方框的中间,方法(函数)都在方框的底部。

3.每个对象提供服务

看完这一小节最大的感受就是,在开发或者理解一个程序时,将每个对象都看做是服务的提供者,将问题从表象中抽取出来,立马想到到底什么样的对象能提供我解决问题的服务呢?—>有助于提高对象的内聚性。

4.被隐藏的具体实现

这一节概括的大致是面向对象中的封装。不希望我们所写的程序赤裸裸地暴露在世人面前。

Why访问控制?

  1. 让客户端程序员无法触及到他们不应该触及的部分
  2. 允许库设计者可以改变内部的工作方式而不用担心会影响到客户端程序员。
public  //公开的
private //私有的
protected  //受保护的
default //java程序默认的访问权限,通常被称为包访问权限。类可以访问在同一个包中其他类的成员。

5.复用具体实现

一旦类被创建并且被测试完,那么在理想情况下,这个类就是代表了一个可用的代码单元。

新的类可以由任意数量、任意类型的其他对象以任意可以实现新的类中想要的功能的方式所组成。就好像—>汽车拥有引擎。

在建立新的类时,应当首先考虑组合,更加简单灵活。

6.继承

public class Goose extends Bird {

    public static void main(String[] args) {
        move();
    }
}
public abstract class Bird {

    static void move() {
        System.out.println("我是Bird----->是父类");
    }

}
//输出 我是Bird----->是父类

父类与子类具有相同的数据类型,还拥有相同的行为,通过继承而产生的类型等价性是理解面向对象程序设计方法内涵的重要门槛。

有两种方法可以使父类和子类产生差异:

  1. 直接在子类中创建新方法
  2. 改变现有父类的方法,覆盖。报告!我想使用相同的方法干点不同的事!
public class Goose extends Bird {

    public static void main(String[] args) {
        move();
    }
    protected static void move(){
        System.out.println("我是Goose------>我是Goose子类");
    }
}
public abstract class Bird {

    static void move() {
        System.out.println("我是Bird----->是父类");
    }

}

//输出 我是Goose------>我是Goose子类
6.1 理解“是一个”和“像是一个”关系

有时候在子类中添加新的接口元素,这样也拓展了接口。这是一种“is-like-a”的关系。新类型具有旧类型的接口,但是他还包含了其他方法,所以他们不完全相同。

有时候父类和子类是完全相同的类型,因为他们具有完全相同的接口。这是一种“is-a”的关系。继承的理想方式,但意义大不。

7.伴随多态的可互换对象

先看一段代码

public class Test {
    public static void main(String[] args) {
      show(new Cat());  // 以 Cat 对象调用 show 方法
      show(new Dog());  // 以 Dog 对象调用 show 方法
                
      Animal a = new Cat();  // 向上转型  
      a.eat();               // 调用的是 Cat 的 eat
      Cat c = (Cat)a;        // 向下转型  
      c.work();        // 调用的是 Cat 的 work
  }  
            
    public static void show(Animal a)  {
      a.eat();  
        // 类型判断
        if (a instanceof Cat)  {  // 猫做的事情 
            Cat c = (Cat)a;  
            c.work();  
        } else if (a instanceof Dog) { // 狗做的事情 
            Dog c = (Dog)a;  
            c.work();  
        }  
    }  
}
 
abstract class Animal {  
    abstract void eat();  
}  
  
class Cat extends Animal {  
    public void eat() {  
        System.out.println("吃鱼");  
    }  
    public void work() {  
        System.out.println("抓老鼠");  
    }  
}  
  
class Dog extends Animal {  
    public void eat() {  
        System.out.println("吃骨头");  
    }  
    public void work() {  
        System.out.println("看家");  
    }  
}

编译器不可能产生传统意义上的函数调用

在OOP中,程序直到被运行时才能确定代码的地址,所以当一个消息发送给一个泛化对象时,必须采用其他的机制。—>后期绑定

在java中,动态绑定是默认行为,不需要添加额外的关键字来实现多态。在C++中,是使用virtual关键字实现的。

8.单根继承机制

所有的类都继承看Object类,终极类。所有对象都可以在堆上容易的创建,那么参数的传递也得到了很大的简化,保证了所以对象都具有某些功能。

在单根继承中,所有的对象都具有一个共用接口,所以他们归根到底都是相同的基本类型。—>提高了生产率。

单根继承也使得java的垃圾回收机制更加容易。不会因为无法确定对象的类型而陷入僵局,极大的简化了系统级别的操作。

9.容器/集合

创建一个容器,然后把不知道到底要多少的对象放在容器中,让它来处理所有细节。

  • 不同的容器提供了不同数据类型的接口和外部行为;
  • 不同的容器对于某些具体的操作具有不同的效率;

在选择容器时,需要依据具体情况需要而定。

9.1参数化类型

向上转型是安全的,向下转型是不安全的。向上转型,因为我知道其父类的类型什么,而在向下转型时,是不清楚所要处理的对象是什么类型的。

javaSE5的重大变化就是加入了参数化类型,在java中成为泛型。参数化类型就是一个编译器可以自动定制作用于特定类型上的类。

10.对象的创建和生命期

对于对象的创建,在C++中,为了追求最大的执行速度,对象的存储空间和生命周期可以在编写程序时确定,可以将这些对象放在堆栈中或静态存储区中。但这样做也牺牲了灵活性,因为必须在编程程序时就确定对象确切的数量、生命周期和类型。

java完全采用了动态内存分配方式。每当想要创建新对象时,就要new关键字new出来一个此对象的动态实例。

对于对象的生命周期,C++可以通过编程确定创建对象的生命周期和存储空间,但这样做会因为不能正确处理而导致内存泄漏。这个问题已经使很多C++项目折戟沉沙!

java则是提供了一种垃圾回收机制,它可以自动发现对象何时不再被使用并继而销毁他。垃圾回收器提供了更高层的保障,可以避免暗藏的内存泄漏问题。

11.异常处理:处理错误

异常是程序中的一些错误,但并不是所有的错误都是异常,并且错误有时候是可以避免的。

  • 用户输入了非法数据。
  • 要打开的文件不存在。
  • 网络通信时连接中断,或者JVM内存溢出。

这些异常有的是因为用户错误引起,有的是程序错误引起的,还有其它一些是因为物理错误引起的。-

要理解Java异常处理是如何工作的,你需要掌握以下三种类型的异常:

  • 检查性异常:最具代表的检查性异常是用户错误或问题引起的异常,这是程序员无法预见的。例如要打开一个不存在文件时,一个异常就发生了,这些异常在编译时不能被简单地忽略。
  • 运行时异常: 运行时异常是可能被程序员避免的异常。与检查性异常相反,运行时异常可以在编译时被忽略。
  • 错误: 错误不是异常,而是脱离程序员控制的问题。错误在代码中通常被忽略。例如,当栈溢出时,一个错误就发生了,它们在编译也检查不到的。

throws 和throw 的区别

throws —> 声明方法抛出异常给上一级【谁调用谁就是上一级】

格式:访问限制修饰符 返回值类型 方法名称()throws 具体异常类型{ }

当我们无法判断读具体异常类型的时候使用Exception/Throwable代替

throw —> 手动引发一个具体异常
自定义异常 —> 编写一个新类,继承Exception/Throwable,在构造方法中访问父类的构造方法。

12.并发编程

进程
程序由指令和数据组成,但这些指令要运行,数据要读写,就必须将指令加载至 CPU,数据加载至内存。在 指令运行过程中还需要用到磁盘、网络等设备。进程就是用来加载指令、管理内存、管理 IO 的。
当一个程序被运行,从磁盘加载这个程序的代码至内存,这时就开启了一个进程。
进程就可以视为程序的一个实例。大部分程序可以同时运行多个实例进程(例如记事本、画图、浏览器 等),也有的程序只能启动一个实例进程(例如网易云音乐、360 安全卫士等)

线程
一个进程之内可以分为一到多个线程。
一个线程就是一个指令流,将指令流中的一条条指令以一定的顺序交给 CPU 执行
Java 中,线程作为最小调度单位,进程作为资源分配的最小单位。 在 windows 中进程是不活动的,只是作 为线程的容器

二者对比
进程基本上相互独立的,而线程存在于进程内,是进程的一个子集
进程拥有共享的资源,如内存空间等,供其内部的线程共享
进程间通信较为复杂
同一台计算机的进程通信称为 IPC(Inter-process communication)
不同计算机之间的进程通信,需要通过网络,并遵守共同的协议,例如 HTTP
线程通信相对简单,因为它们共享进程内的内存,一个例子是多个线程可以访问同一个共享变量
线程更轻量,线程上下文切换成本一般上要比进程上下文切换低

并发
单核 cpu 下,线程实际还是 串行执行 的。操作系统中有一个组件叫做任务调度器,将 cpu 的时间片(windows 下时间片最小约为 15 毫秒)分给不同的程序使用,只是由于 cpu 在线程间(时间片很短)的切换非常快,人类感觉是同时运行的 。总结为一句话就是: 微观串行,宏观并行 ,
一般会将这种线 程轮流使用 CPU 的做法称为并发, concurrent

12.1.java与Internet

C/S是Client/Server的缩写。服务器通常采用高性能的PC、工作站或小型机,并采用大型数据库系统。客户端需要安装专用的客户端软件。

B/S是Brower/Server的缩写,客户机上只要安装一个浏览器(Browser),服务器安装Oracle、Sybase、InFORMix或 SQL Server等数据库。在这种结构下,用户界面完全通过WWW浏览器实现,一部分事务逻辑在前端实现,但是主要事务逻辑在服务器端实现。浏览器通过Web Server 同数据库进行数据交互。

客户端编程!这里要提到一个过时的技术叫做Applet(小应用程序)。Java 是通过 applet 以及使用 Java Web Start来进行客户端编程的。

服务端编程!过去,服务器端编程都是通过使用 Perl 、Python 、C++或语言编写 CGI 程序而实现的,但却造成了从此之后更复杂的系统。其中就包括基于Java 的Web 服务器,它让你用java编写被称为servlet的程序来实现服务器端编程。servlet 及其衍生物 JSP,是许多开发网站的公司迁移到Java上的两个主要原因,尤其是因为它们消除了处理具有不同能力的浏览器时所遇到的问题。
plet(小应用程序)。Java 是通过 applet 以及使用 Java Web Start来进行客户端编程的。

服务端编程!过去,服务器端编程都是通过使用 Perl 、Python 、C++或语言编写 CGI 程序而实现的,但却造成了从此之后更复杂的系统。其中就包括基于Java 的Web 服务器,它让你用java编写被称为servlet的程序来实现服务器端编程。servlet 及其衍生物 JSP,是许多开发网站的公司迁移到Java上的两个主要原因,尤其是因为它们消除了处理具有不同能力的浏览器时所遇到的问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

乔墩墩123

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值