Java基础知识复习笔记(2)

作者: TyiMan | 来源:发表于2016-05-10 23:56 被阅读458次

    1. Java接口和抽象类的区别

    语法上:

    • 抽象类可以提供成员方法的实现细节,而接口中只能存在public abstract 方法;
    • 一个类只能继承一个抽象类,而一个类却可以实现多个接口。
    • 抽象类可以在不提供接口方法的具体实现的情况下实现接口。
    • 接口中不能含有静态代码块以及静态方法,而抽象类可以有静态代码块和静态方法;
    • 抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是public static final类型的;

    设计层面:

    • 抽象类是对一种事物的抽象,即对类抽象,而接口是对行为的抽象。抽象类是对整个类整体进行抽象,包括属性、行为,但是接口却是对类局部(行为)进行抽象。例如:设计一个鸟类Bird类,其中包括一些鸟类的公共属性和方法,如:定义羽毛颜色,eat()方法等,再设计一个接口Fly接口,因为并不是所有的鸟都具有飞行的行为,所以只有能飞的鸟才去实现Fly接口。
    • 设计层面不同,抽象类作为很多子类的父类,它是一种模板式设计。而接口是一种行为规范,它是一种辐射式设计。模板设计,A为抽象类,A1,A2都继承A,如果公共部分需要修改,只需在A中进行改变,A1,A2都需要改变。但是接口如果改变,则所有实现都需要进行改变。

    2. Java的值传递和引用传递

    对象被值传递,意味着传递了对象的一个副本。因此,就算是改变了对象副本,也不会影响源对象的值。

    对象被引用传递,意味着传递的并不是实际的对象,而是对象的引用。因此,外部对引用对象所做的改变会反映到所有的对象上。

    • Java 应用程序有且仅有的一种参数传递机制,即按值传递
    • 原始类型就是传值,但Java参数的引用传递并不是传递对象的引用而是引用变量的副本
    class person {
      public String name = "Jack";
     
      //定义一个改变对象属性的方法
      public void changeName(Person p) {
        p.name = "Rose";
      }
    
    public static void main(String[] args) {
      //定义一个Person对象,person是这个对象的引用
      Person person = new Person();
      //先显示这个对象的name属性
      System.out.println(person.name);
      //调用changeName(Person p)方法
      changeName(person);
      //再显示这个对象的name属性,看是否发生了变化
      System.out.println(person.name);
    }
    

    输出结果:

    第一次显示:“Jack”
    第二次显示:“Rose”

    上述操作的内存分配
    1. 实例化Person对象的时候,实际分配了两个对象:新创建的Person类的实体对象和指向该对象的引用变量person。在堆中为Person对象分配内存空间,但是引用变量在栈中分配内存空间,其中person引用变量指向Person对象的首地址,指向Person对象。
    2. 调用changeName方法时,传递的值是person引用变量,因为Java只有值传递,所以方法中p变量为person引用变量的副本,重新为p分配地址空间。
    3. p为person应用的变量的副本,p的值与person相同,也存放着Person对象的首地址,也指向Person对象,所以p的操作,会改变Person对象的值。
    4. 总结:Java对象作为方法的参数进行传递的时候,其传递的是引用变量的副本,但两个引用变量指向同一个地址空间(即对象的地址),但在方法中无法改变原引用变量。

    重点注意:String,Integer, Double等immutable类型因为没有提供自身修改的函数,每次操作都是新生成一个对象,所以要特殊对待,可以认为是传值。Integer 和 String 一样,保存value的类变量是Final属性,无法被修改,只能被重新赋值/生成新的对象。 当Integer 做为方法参数传递进方法内时,对其的赋值都会导致 原Integer 的引用被指向了方法内的栈地址,失去了对原类变量地址的指向。对赋值后的Integer对象做得任何操作,都不会影响原来对象。

    3. 进程和线程

    • 两者的定义
      进程是具有一定独立功能的程序在数据集上的一次活动,它拥有操作系统分配给它独自使用的系统资源,所以,进程也是操作系统进行资源分配和调度的一个独立单元。
      线程是进程中执行运算的最小单位,是进程的实体,它是CPU调度和分派的基本单位,线程只拥有一点在运行中必不可少的资源(程序计数器,一组寄存器和栈),此外,线程和同属进程的其他线程共享进程的资源。
    • 两者的关系
      (1) 一个线程只能属于一个进程,一个进程可以有多个线程,但至少有一个线程
      (2) 操作系统把资源分配给进程,同一个进程的所有线程共享该进程的资源
      (3) 线程是进程中的执行单元,CPU执行的是线程,此外,线程也是进程内的可调度单元。
    • 两者的区别
      (1) 调度执行: 进程在操作系统中独立运行,由操作系统进行调度,线程必须依赖进程存在,由进程进行调度。
      (2) 并发性: 进程和线程都可以并发执行,但是线程划分更小,所以并发性更高
      (3) 拥有资源 进程是拥有操作系统资源的基本单元,线程共享所属进程的资源
      (4) 系统开销 创建和撤销进程的开销远远大于创建和撤销线程的开销。
    • 两者的通信方式
      (1)进程间的通信方式
      • 管道(Pipe):管道可用于具有亲缘关系进程间的通信,允许一个进程和另一个与它有共同祖先的进程之间进行通信。
      • 命名管道(named pipe): 命名管道克服了管道没有名字的限制,因此,除具有管道所具有的功能外,它还允许无亲缘关系进程间的通信。命名管道在文件系统中有对应的文件名。命名管道通过命令mkfifo或系统调用mkfifo来创建。
      • 信号(Signal):信号是比较复杂的通信方式,用于通知接受进程有某种事件发生,除了用于进程间通信外,进程还可以发送 信号给进程本身;linux除了支持Unix早期信号语义函数sigal外,还支持语义符合Posix.1标准的信号函数sigaction(实际上,该 函数是基于BSD的,BSD为了实现可靠信号机制,又能够统一对外接口,用sigaction函数重新实现了signal函数)。
      • 消息(Message)队列:消息队列是消息的链接表,包括Posix消息队列system V消息队列。有足够权限的进程可以向队列中添加消息,被赋予读权限的进程则可以读走队列中的消息。消息队列克服了信号承载信息量少,管道只能承载无格式字 节流以及缓冲区大小受限等缺
      • 共享内存:使得多个进程可以访问同一块内存空间,是最快的可用IPC形式。是针对其他通信机制运行效率较低而设计的。往往与其它通信机制,如信号量结合使用,来达到进程间的同步及互斥。
      • 内存映射(mapped memory):内存映射允许任何多个进程间通信,每一个使用该机制的进程通过把一个共享的文件映射到自己的进程地址空间来实现它。
      • 信号量(semaphore):主要作为进程间以及同一进程不同线程之间的同步手段。
      • 套接口(Socket):更为一般的进程间通信机制,可用于不同机器之间的进程间通信。

    (2)线程间的通信方式

    • 共享内存,可以通过内部类来实现共享变量
    • 管道 线程间建立流管道

    相关文章

      网友评论

      • harveystack:管道?能展开说说吗?
        TyiMan:@harveystack 我又简单整理了一下进程间通信方式的介绍,http://www.jianshu.com/p/c1015f5ffa74,希望对你有所帮助
      • Timmy_gzw:写的很好,支持一下!

      本文标题:Java基础知识复习笔记(2)

      本文链接:https://www.haomeiwen.com/subject/tupyrttx.html