可从面向对象、主要作用和组成部分三方面对比。如下图所示:
1). 主要面向开发人员。开发人员在软件开发时使用的SDK(Software Development Kit 一般指软件开发包),它提供了Java的开发环境和运行环境。
2). 如果你电脑安装了JDK,那么你不仅可以开发Java程序,也同时拥有了运行Java程序的平台。
3). 是整个Java开发环境的核心组件,并提供编译、调试和运行一个 java 程序所需要的所有工具,可执行普通文件和二进制文件,是一个平台特定的软件,其中包括了Java运行环境,Java工具和Java基础类库。
1). 主要面向程序使用者。
2). 如果你电脑安装了JRE,那么你的电脑只能运行Java程序,不能从事Java开发。
3). 包含JVM标准实现及Java核心类库。它包括Java虚拟机、Java平台核心类和支持文件。它不包含开发工具(编译器、调试器等)。同时还包含了编译java源码的编译器javac,还包含了很多java程序调试和分析的工具:console,jvisualvm等工具软件,还包含了java程序编写所需的文档和demo例子程序。
1). JRE是个运行环境,JDK是个开发环境。因此,开发程序时,写的Java程序就是在JDK上,而运行Java程序的时候,就需要JRE。
2).JDK包含了JRE,但是,JRE可以独立安装的。
3). JDK、JRE、JVM的关系
1)、Java程序在执行过程中用到一套JDK工具,其中java.exe是指(B)
A.Java文档生成器
B.Java解释器
C.Java编译器
D.Java类分解器
2)、JDK安装目录下具有多个文件夹和一些网页文件,其中为java使用者提供的一些已经编好的范例程序的文件夹是(demo)
3)、JDK安装目录下主要文件夹及文件功能:
(1)bin文件夹:提供JDK工具程序,包括javac、java、javadoc、appletviewer等可执行程序。
(2)demo文件夹:Sun公司为Java使用者提供给的一些已经编写好的范例程序。
(3)jre文件夹:存放Java运行环境文件。
(4)lib文件夹:存放Java的类库文件,即工具程序使用的Java类库。JDK中的工具程序大多也是由Java编写而成。
(5)include文件夹:存放用于本地方法的文件。
4)、( A)称为JAVA开发包或JAVA开发工具,是一个写JAVA的Applet小程序和应用程序的程序开发环境。
A.JDK
B.JRE
C.JVM
5)、(C )可以实现Java程序的跨平台运行。
A.JDK
B.JRE
C.JVM
覆盖/重写(Override):
是指子类对父类方法的一种重写,只能比父类抛出更少的异常,访问权限不能比父类的小。被覆盖的方法不能是 private 的,否则相当于只是在子类中重新定义了一个方法(父类方法私有,子类不存在复写)。
子类复写父类的方法时,要求返回值类型、方法名、参数列表必须一致,方法体可以修改。
重载(Overload):
在一个类(class)中出现了同名不同参数的方法。
参数类型不同、参数个数不同、参数顺序不同。(方法的重载与方法的返回值类型无关)
不可以,因为 Java 中调用函数并不需要强制赋值。
如下两个方法:
void f(){}
int f(){ return 1;}
只要编译器可以根据语境明确判断出语义,比如在 int x = f();中,那么的确可以据此区分重载方法。不过, 有时你并不关心方法的返回值,你想要的是方法调用的其他效果 (这常被称为 “为了副作用而调用”),这时你可能会调用方法而忽略其返回值,所以如果像下面的调用:
fun();
此时 Java 如何才能判断调用的是哪一个 f() 呢?别人如何理解这种代码呢?所以,根据方法返回值来区分重载方法是行不通的。
抽象类就是不能使用new方法进行实例化的类,即没有具体实例对象的类。
抽象类有点类似于“模版”的作用,目的是根据其格式来创建和修改新的类,对象不能由抽象类直接创建,只可以通过抽象类派生出新的子类,再由其子类来创建对象,当一个类被声明为抽象类时,要在这个类前面加上修饰符abstract,在抽象类中的成员方法可以包括一般方法和抽象方法。
抽象方法就是以abstract修饰的方法,这种方法只声明返回的数据类型,方法名称和所需要的参数,没有方法体,也就是说抽象方法只需要声明而不需要实现,当一个方法为抽象方法时,意味着这个方法必须被子类的方法所重写,否则其子类的该方法仍然是abstract的,而这个子类也必须是抽象的,即声明为avstract。
一定是父类,但它不会是最顶层父类。一般要求:抽象类都会有子类,目的是让子类来复写抽象类中的抽象方法,完成符合子类自己特有的行为属性。
注意:如果一个子类继承一个抽象类,子类没有将抽象类中的所有抽象方法全部复写掉,相当于这个子类中依然有抽象方法,这个子类也会是一个抽象类。
不能。一般抽象类中都有抽象方法,如果这个类可以让创建对象,就意味着可以去调用抽象方法了,由于抽象方法是没有方法体,调用是没有任何的意义。
有。虽然抽象类不能创建对象,但是它有子类,子类的构造方法中有隐式的super语句,需要找父类的构造方法。抽象类中的构造方法是为创建子类时进行初始化而提供服务的。
能。它的存在只有一个目的,就是不让创建这个类的对象。它的存在是为了完成一种设计模式(适配器设计模式)。如:
abstract class Cat {
public static void sayHi() {
System. out. println("hi~");
}
}
相同点:
1)都不能被直接实例化,都可以通过继承实现其抽象方法。
2)都是面向抽象编程的技术基础,实现了诸多的设计模式。
不同点:
1)抽象类只能单继承,接口可以继承多个父接口;
2)抽象类中可以没有抽象方法,接口中的方法必须是抽象方法;
3)抽象类中可有普通的成员变量,接口中变量必须是 static final 类型,必须被初始化(其实都是常量) ;
4)接口是一组行为规范,抽象类是一个不完全的类;
5)Java8 中接口中会有 default 方法,即方法可以被实现;
1)如果要创建不带任何方法定义和成员变量的基类,那么就应该选择接口而不是抽象类;
2)如果知道某个类应该是基类,那么第一个选择的应该是让它成为一个接口,只有在必须要有方法定义和成员变量的时候,才应该选择抽象类。因为抽象类中允许存在一个或多个被具体实现的方法,只要方法没有被全部实现该类就仍是抽象类。
abstract不能和final、static、private共存。
因为:
final修饰的类不能被继承,修饰的方法不能被复写;而abstract关键字修饰的类要求必须有子类,修饰的方法要求子类必须复写。
static修饰的方法可以通过类名直接调用;abstract关键字修饰的方法是没有方法体,如果可以共存,意味着可以通过类名直接调用。
private修饰的方法只能在本类中使用;abstract修饰的方法要求子类复写的。私有了,子类根本就继承不到,没法复写。
1、都是面向对象的语言,都支持封装、继承和多态(面向对象的三大特性:封装、继承、多态);
2、指针:Java 不提供指针来直接访问内存,使得程序更加安全;
3、继承: Java 的类是单继承的,C++ 支持多重继承; Java 通过一个类实现多个接口来实现 C++ 中的多重继承; Java 中类不可以多继承,但是接口可以多继承;
4、内存: Java 有自动内存管理机制,不需要程序员手动释放无用内存。(垃圾回收器:Gabage Collection)
值传递:是指对象被值传递,意味着传递了对象的一个副本,即使副本被改变,也不会影响原来的对象。
引用传递:是指对象被引用传递,意味着传递的并不是实际的对象,而是对象的引用。
左侧为引用传递,右侧为值传递:
[外链图片转存失败(img-Bcig4GZA-1565011896968)(C:\Users\DELL\Documents\Tencent Files\2461540049\FileRecv\MobileFile\img-612edf3aly1g57f8cn6dbg20dw07iwk9.gif)]
包含一些Java语言的核心类(eg:String、Math、Integer、System、Thread),在默认情况下,编译器会将这个包自动引入到任何的java程序中,所以此包也是唯一一个可以不用引入(import)就可以直接使用其中类的包。
这里面是所有输入输出有关的类,比如文件操作等。
java New IO,为了完善io包中的功能,提高io包中性能而写的一个新包 ,NIO非堵塞的应用。常用方法有:
Buffer | 一个用于特定基本类型数据的容器。 |
---|---|
ByteBuffer | 字节缓冲区。 |
ByteOrder | 字节顺序的类型安全枚举。 |
CharBuffer | 字符缓冲区。 |
DoubleBuffer | double 缓冲区。 |
FloatBuffer | float 缓冲区。 |
IntBuffer | int 缓冲区。 |
LongBuffer | long 缓冲区。 |
MappedByteBuffer | 直接字节缓冲区,其内容是文件的内存映射区域。 |
ShortBuffer | short 缓冲区。 |
包含一些实用工具类以及数据结构类,如定义系统特性、使用与日期日历相关的函数、集合、堆栈等。
Deque | 一个线性 collection,支持在两端插入和移除元素。 |
---|---|
Enumeration | 实现 Enumeration 接口的对象,它生成一系列元素,一次生成一个。 |
Iterator | 对 collection 进行迭代的迭代器。 |
List | 有序的 collection(也称为序列)。 |
ListIterator | 系列表迭代器,允许程序员按任一方向遍历列表、迭代期间修改列表,并获得迭代器在列表中的当前位置。 |
Map |
将键映射到值的对象。 |
Map.Entry |
映射项(键-值对)。 |
Queue | 在处理元素前用于保存元素的 collection。 |
Set | 一个不包含重复元素的 collection。 |
包含用于访问数据库的类,Connection, Statement,ResultSet等。常用方法有:
Date | 一个包装了毫秒值的瘦包装器 (thin wrapper),它允许 JDBC 将毫秒值标识为 SQL DATE 值。 |
---|---|
DriverManager | 管理一组 JDBC 驱动程序的基本服务。 |
DriverPropertyInfo | 用于建立连接的驱动程序属性。 |
SQLPermission | SecurityManager 将用来检查在 applet 中运行的代码何时调用 DriverManager.setLogWriter 方法或 DriverManager.setLogStream (不建议使用)方法的权限。 |
Time | 一个与 java.util.Date 类有关的瘦包装器 (thin wrapper),它允许 JDBC 将该类标识为 SQL TIME 值。 |
Timestamp | 一个与 java.util.Date 类有关的瘦包装器 (thin wrapper),它允许 JDBC API 将该类标识为 SQL TIMESTAMP 值。 |
Types | 定义用于标识一般 SQL 类型(称为 JDBC 类型)的常量的类。 |
这个是JSP,Servlet等使用到的类。
包含执行与网络相关的操作的类,常用Socket、URI、URL、URLConnection等类。常用方法有:
ServerSocket | 此类实现服务器套接字。 |
---|---|
Socket | 此类实现客户端套接字(也可以就叫“套接字”)。 |
SocketAddress | 此类表示不带任何协议附件的 Socket Address。 |
SocketImpl | 抽象类 SocketImpl 是实际实现套接字的所有类的通用超类。 |
SocketPermission | 此类表示通过套接字对网络的访问。 |
URI | 表示一个统一资源标识符 (URI) 引用。 |
URL | 类 URL 代表一个统一资源定位符,它是指向互联网“资源”的指针。 |
URLClassLoader | 该类加载器用于从指向 JAR 文件和目录的 URL 的搜索路径加载类和资源。 |
URLConnection | 抽象类 URLConnection 是所有类的超类,它代表应用程序和 URL 之间的通信链接。 |
数学及科学计算相关的包,提供用于执行任意精度整数算法 (BigInteger) 和任意精度小数算法 (BigDecimal) 的类。
Map 接口和 Collection 接口是所有集合框架的父接口。
[外链图片转存失败(img-5bPuhWAX-1565011896970)(C:\Users\DELL\AppData\Roaming\Typora\typora-user-images\1563690671924.png)][外链图片转存失败(img-VINuk0z9-1565011896972)(C:\Users\DELL\AppData\Roaming\Typora\typora-user-images\1563690701425.png)]
1、Collection 接口的子接口包括:Set 接口和 List 接口;
2、Map 接口的实现类主要有:HashMap、TreeMap、Hashtable、ConcurrentHashMap 以及 Properties 等;
3、Set 接口的实现类主要有:HashSet、TreeSet、LinkedHashSet 等;
4、List 接口的实现类主要有:ArrayList、LinkedList、Stack 以及 Vector 等。
HashMap是基于哈希表实现的,每一个元素是一个key-value对,其内部通过单链表解决冲突问题,容量不足时(也就是超过了阀值),同样会自动增长。HashMap是非线程安全的,只是用于单线程环境下,多线程环境下可以采用concurrent并发包下的concurrentHashMap。HashMap 实现了Serializable接口,因此它支持序列化,实现了Cloneable接口,能被克隆。
HashMap存数据的过程是:
HashMap内部维护了一个存储数据的Entry数组,HashMap采用链表解决冲突,每一个Entry本质上是一个单向链表。当准备添加一个key-value对时,首先通过hash(key)方法计算hash值,然后通过indexFor(hash,length)求该key-value对的存储位置,计算方法是先用hash&0x7FFFFFFF后,再对length取模,这就保证每一个key-value对都能存入HashMap中,当计算出的位置相同时,由于存入位置是一个链表,则把这个key-value对插入链表头。
HashMap中key和value都允许为null。key为null的键值对永远都放在以table[0]为头结点的链表中。
HashMap的存储结构,如下图所示:
图中,紫色部分即代表哈希表,也称为哈希数组,数组的每个元素都是一个单链表的头节点,链表是用来解决冲突的,如果不同的key映射到了数组的同一位置处,就将其放入单链表中。
HashMap内存储数据的Entry数组默认是16,如果没有对Entry扩容机制的话,当存储的数据一多,Entry内部的链表会很长,这就失去了HashMap的存储意义了。所以HasnMap内部有自己的扩容机制。
Hashtable同样是基于哈希表实现的,同样每个元素是一个key-value对,其内部也是通过单链表解决冲突问题,容量不足(超过了阀值)时,同样会自动增长。
Hashtable也是JDK1.0引入的类,是线程安全的,能用于多线程环境中。
Hashtable同样实现了Serializable接口,它支持序列化,实现了Cloneable接口,能被克隆。
Hashtable继承自Dictionary类;
HashMap继承自AbstractMap类。但二者都实现了Map接口。
HashMap 没有考虑同步,是线程不安全的;
Hashtable 使用了 synchronized 关键字,是线程安全的。
HashMap把Hashtable的contains方法去掉了,只有containsValue和containsKey,因为contains方法容易让人引起误解。
Hashtable则保留了contains,containsValue和containsKey三个方法,其中contains和containsValue功能相同。
HashMap允许 null 作为 Key;Hashtable不允许 null 作为 Key。
Hashtable、HashMap都使用了 Iterator。而由于历史原因,Hashtable还使用了Enumeration的方式 。
HashTable直接使用对象的hashCode。而HashMap重新计算hash值。
HashTable在不指定容量的情况下的默认容量为11,而HashMap为16;
Hashtable不要求底层数组的容量一定要为2的整数次幂,而HashMap则要求一定为2的整数次幂;
更为详细的了解,访问地址:https://www.cnblogs.com/williamjie/p/9099141.html
r。而由于历史原因,Hashtable还使用了Enumeration的方式 。
HashTable直接使用对象的hashCode。而HashMap重新计算hash值。
HashTable在不指定容量的情况下的默认容量为11,而HashMap为16;
Hashtable不要求底层数组的容量一定要为2的整数次幂,而HashMap则要求一定为2的整数次幂;
更为详细的了解,访问地址:https://www.cnblogs.com/williamjie/p/9099141.html