赞
踩
Java虚拟机是一种用于计算设备的规范,它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的。Java之所以被称作是平台无关就是因为它有JVM,源程序通过编译为字节码文件,字节码文件是可以跨平台运行的。
JDK是Java开发包,主要包括开发环境和运行环境(JRE),而JRE是指Java运行环境,主要面向的是Java程序的使用者。
static表示静态的意思,可以用来修饰变量、方法以及代码块,修饰一个变量或者方法时表示所修饰的对象是属于整个类的。而静态代码块是在类加载的时候执行的。
Java中无法重写private和static修饰的方法,原因是一个方法使用private修饰的时候这个方法是不能被继承的。使用static修饰的时候,这个方法在编译的时候就与类进行了静态绑定,而方法覆盖是运行时动态绑定的,所以也不可以重写。
不可以在static中访问非static变量,如果一个类没有实例化,可以调用静态方法,但非静态变量是属于对象的,是不能被调用的。
Java中基本的数据类型有4类8种;
整型:byte,short,int,long
浮点型:float,double
逻辑型:boolean
字符型:char
自动拆装箱是指基本数据类型的对应包装类之间的相互转换。
方法覆盖:发生在子类与父类之间,子类可以重写继承自父类的方法。方法覆盖需要满足“两小两同一大”的规则。两小:返回值类型和抛出的异常等于父类或更小;两同:方法名和参数列表与父类相同;一大:访问权限等于父类或更大。
方法重载:发生在同一个类中,方法名相同,以参数列表作为区别,返回值也可以不同。
构造方法是为了在创建对象时,给对象属性初始化值所需要的方法,这个方法没有返回值,方法名与类名相同。构造方法重载就是拥有不同参数列表的构造方法。
Java不支持多继承,但是可以实现多个接口。
接口和抽象类的区别是什么?
一个类可以实现多个接口但只能继承一个抽象类
接口中的属性默认用final修饰,抽象类中可以有非final的变量
接口中所有方法都是默认abstract的,而抽象类可包含抽象方法和非抽象方法
接口中的方法默认是public,而抽象类可以是public,private,protected。
值传递:在方法被调用时,实参通过形参把它的内容副本传入方法内部,形参接收到的内容是实参值的一个拷贝,因此在方法内对形参的任何操作,都仅仅是对这个副本的操作,不影响原始值的内容。
引用传递:”引用”也就是指向真实内容的地址值,在方法调用时,实参的地址通过方法调用被传递给相应的形参,在方法体内,形参和实参指向通愉快内存地址,对形参的操作会影响的真实内容。
进程是程序的一次执行,而线程是比进程更小的执行单元。
继承Thread,实现Runnable接口,实现Callable接口。
最常使用的是实现Runnable和Callable接口,可以多个线程间可以实现资源共享。
新建状态:线程对象被创建
就绪状态:表示线程已经准备好运行了
运行状态:线程正在占有CPU时间片,正在运行
阻塞状态:线程由于某些原因放弃了cpu使用权,处于阻塞态
死亡状态:线程发生异常死亡或者是执行完毕。
同步方法是指使用synchronized修饰方法,是对对象加锁;同步代码块即有synchronized关键字修饰的语句块。 被该关键字修饰的语句块会自动被加上内置锁,锁的是括号里的对象,从而实现同步。
JVM是通过进入和退出Monitor对象来实现同步,监视器监视一块同步代码块,确保一次只有一个线程执行同步代码块。每一个监视器都和一个对象引用相关联。线程在获取锁之前不允许执行同步代码。
死锁是指线程都在等待别的线程释放资源。死锁形成的4个条件:
1.互斥
2.请求和保持
3.不可抢占
4.循环等待
防止死锁只需要破坏死锁的四个条件之一即可,可以对访问资源的顺序加以规定,按照顺序加锁访问,然后释放。这样就不会导致死锁。
主要有Collection和Map,Collection又分List和Set等。
克隆(cloning)或者是序列化(serialization)的语义和含义是跟具体的实现相关的。因此,应该由集合类的具体实现来决定如何被克隆或者是序列化。
Iterator接口提供了很多对集合元素进行迭代的方法。
terator可用来遍历Set和List集合,但是ListIterator只能用来遍历List。
Iterator对集合只能是前向遍历,ListIterator既可以前向也可以后向。
ListIterator实现了Iterator接口,并包含其他的功能,比如:增加元素,替换元素,获取前一个和后一个元素的索引,等等。
快速失败:当你迭代一个集合时,如果有另一个线程对其修改,就会抛出一ConcurrentModification 异常。 在 java.util 包下的都是快速失败。
安全失败:指的是在迭代的时候会对底层是数据做一个拷贝,在修改的时候不会影响到底层,不会抛出异常。在 java.util.concurrent 包下的全是安全失败的。
HashMap底层实现是以数组+链表的形式,在向HashMap里put一个数据时,先对key进行hash得到一个hashcode值,然后按照hashcode值查找其需要存储的位置 。如果发生碰撞,将这个entry加入到那个链表中。
因为需要通过hashCode()和equals()来确定一个对象的唯一性,这在程序中经常用到,比如Set需要判断两个对象是否相等,它先会判断hashCode值是否相等,如果相等的话还会再调用equals判断。
HashMap不是线程安全的HashTable是线程安全的
HashMap的键值可以为空,Hashtable的键值不可以为空
HashMap继承的Map接口,Hashtable继承的Dictionary接口
Array是定长的,ArrayList是可变长度的
Array可以存储基本类型和对象,ArrayList只可以存储对象
ArrayList功能更多
底层实现不同,ArrayList是采用数组的形式,LinkedList是采用双向链表的形式
ArrayList更适合查询,LinkedList更适合插入和删除
Comparable接口属于lang包,有一个comparaTo()方法,用于当前对象与其他对象比较。
Comparator接口属于util包下,有一个 compare(Object obj1, Object obj2) 方法,用于比较传入的两个对象。
PriorityQueue 是一个基于优先级堆的无界队列,它的元素都以他们的自然顺序有序排列。
在它创建的时候,我们可以可以提供一个比较器 Comparator 来负责PriorityQueue 中元素的排序。
PriorityQueue 不允许 `` null元素,不允许不提供自然排序的对象,也不允许没有任何关联 Comparator 的对象。
最后,PriorityQueue 不是线程安全的,在执行入队和出队操作它需要 O(log(n)) 的时间复杂度。
你了解大O符号(big-O notation)么?你能给出不同数据结构的例子么?
有序数组查询容易插入难,无序数组插入容易查询难
根据需求不同进行选择
基于应用的需求来选择使用正确类型的集合,这对性能来说是非常重要的。例如,如果元素的大小是固定的,并且知道优先级,我们将会使用一个 Array ,而不是 ArrayList 。
一些集合类允许我们指定他们的初始容量。因此,如果我们知道存储数据的大概数值,就可以避免重散列或者大小的调整。
总是使用泛型来保证类型安全,可靠性和健壮性。同时,使用泛型还可以避免运行时的 ClassCastException 异常。
在 Map 中使用 JDK 提供的不可变类作为一个 key,这样可以避免 hashcode 的实现和我们自定义类的 equals 方法。
应该依照接口而不是实现来编程。
返回零长度的集合或者数组,而不是返回一个 null ,这样可以防止底层集合是空的。
Enumeration 跟 Iterator 相比较快两倍,而且占用更少的内存。
但是,Iterator 相对于 Enumeration 更安全,因为其他线程不能修改当前迭代器遍历的集合对象。同时,Iterators 允许调用者从底层集合中移除元素,这些 Enumerations 都没法完成。
HashSet无序,TreeSet有序
目的:释放无用的资源,节省内存的消耗。
(1)当应用程序空闲时,即没有应用线程在运行时,GC会被调用。
(2)Java堆内存不足时,GC会被调用。
两者调用的行为并没有什么不同,用于提示jvm进行垃圾回收。
在一个无用的对象被回收前,会调用其finalize()方法。
不会立即回收,会在下一个GC周期时回收释放。
Java堆主要分为新生代、老年代和永久代。
永久代一般存储静态变量和运行时对象
但是在JDK1.8,永久代被替换为元数据区:
移除了永久代(PermGen),替换为元空间(Metaspace)
永久代中的 class metadata 转移到了 native memory(本地内存,而不是虚拟机);
永久代中的 interned Strings 和 class static variables 转移到了 Java heap;
永久代参数 (PermSize MaxPermSize) -> 元空间参数(MetaspaceSize MaxMetaspaceSize)
串行(serial)收集器和吞吐量(throughput)收集器的区别是什么?
在Java中,对象什么时候可以被垃圾回收?
在没有引用指向这个对象时,在下次GC周期会对其进行回收。
永久代不会发生垃圾回收,如果永久代满了就会触发FullGC。
RuntimeException:运行时异常,可以由系统自动检测。比如数组越界,空指针异常等。
CheckedException:受检查的异常,表示程序可以处理的异常,需要在程序中写处理逻辑。
Exception:表示需要系统检测或者程序处理的错误,一般是因为程序逻辑的错误引起的。
Error:系统或者程序无法处理的错误,比如java运行环境的内部错误或者硬件错误。
throw:用在方法中,抛出一个异常对象。
throws:用在方法头后边,表示此方法可能会抛出的异常。
在异常处理完成之后,异常对象将不再会被引用,将会在下一次GC被回收掉。
finally:配合try…catch使用,无论是否发生异常,finally中的代码块都会执行,若finally中有return语句,还会覆盖try中的return语句。
finalize():在对象被回收准备示范内存的时候执行。
是用于访问数据库并且执行SQL语句的JavaAPI。
解释下驱动(Driver)在JDBC中的角色。
Class.forName()方法有什么作用?
返回与给定的字符串名称相关联类或接口的Class对象。
PreparedStatement采取预编译,减少编译时间,也就提高了执行速度。其次其安全性高,可以防止SQL注入。
数据库连接池负责分配、管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个;释放空闲时间超过最大空闲时间的数据库连接来避免因为没有释放数据库连接而引起的数据库连接遗漏。 这项技术能明显提高对数据库操作的性能。
全称Remote Method Invocation即远程方法调用,主要应用于分布式系统中,它允许运行在一个Java虚拟机上的对象调用运行在另一个Java虚拟机上的对象的方法,是纯Java的网络分布式应用系统的核心解决方案之一。
RMI目前使用Java远程消息交换协议JRMP(Java Remote Messaging Protocol)进行通信。
就是把对象的使用和对象的创建相分离,我们在服务器端定义类,定义开放哪些方法,比如接口、抽象类,并创建对象;在客户端调用对象的方法,比如实现接口、继承抽象类。
分为四层:存根层、骨架层、远程引用层、传输层。
存根和骨架层,用来拦截发送的请求,并重定向发送给远程服务器
远程应用层,用来处理对服务器中对象的引用,与客户机建立点对点的连接
传输层,基于tcp ip协议,并有层防火墙
远程接口用来标识哪些功能接口可以被非本地虚拟机调用,远程对象必须要直接或者是间接实现远程接口。实现了远程接口的类应该声明被实现的远程接口,给每一个远程对象定义构造函数,给所有远程接口的方法提供实现。
用来存储和获取在远程对象注册表里面的远程对象的引用,其所有的方法均接受一个String类型的URL格式参数
RMI的绑定就是将一个对象赋给一个URI,让客户端可以通过这个URI访问该对象。
服务端使用Naming.rebind(URI,object)绑定对象给URI。
客户端使用Naming.lookup(URI)来获取这个对象。
bind:如果URI已经与其它对象绑定,就会抛出NameAlreadyBoundException。
rebind:如果该名字已经与其它对象绑定,不会抛出NameAlreadyBoundException,会使用当前对象覆盖之前绑定的对象。
编译所有的源文件。
使用rmic生成stub。
启动rmiregistry。
启动RMI服务器。
运行客户端程序。
stub(存根):扮演了远程对象的代表或者代理的角色。调用者在本地stub上调用方法,它负责在远程对象上执行方法。
RMI 子系统实现基于引用计数的“分布式垃圾回收”(DGC),以便为远程服务器对象提供自动内存管理设施。
当客户机创建(序列化)远程引用时,会在服务器端 DGC 上调用 dirty()。当客户机完成远程引用后,它会调用对应的 clean() 方法。
当应用程序希望把内存对象跨网络传递到另一台主机或者是持久化到存储的时候,就必须要把对象在内存里面的表示转化成合适的格式。这个过程就叫做Marshalling,反之就是demarshalling。
序列化,实现Serialization(序列化)和Deserialization(反序列化)的对象必须实现serializable接口,序列化是将对象变成字节流,存储到磁盘或网络。反序列化是序列化的反过程。
Servlet就是一个接口,servlet接口定义的是一套处理网络请求的规范。
GenericServlet是 Servlet 接口和 ServletConfig 接口的实现类。 是一个抽象类. 其中的 service 方法为抽象方法。
HttpServlet继承自 GenericServlet,针对于 HTTP 协议所定制。
Servlet 生命周期可被定义为从创建直到毁灭的整个过程。
- Servlet 通过调用 init () 方法进行初始化。
- Servlet 调用 service() 方法来处理客户端的请求。
- Servlet 通过调用 destroy() 方法终止(结束)。
- 最后,Servlet 是由 JVM 的垃圾回收器进行垃圾回收的。
通过IP地址。
状态行:包括协议版本Version、状态码Status Code、回应短语;
响应头:包括搭建服务器的软件,发送响应的时间,回应数据的格式等信息;
响应正文:就是响应的具体数据。
cookie是保存在客户端的访问信息。在请求时,会发送至服务端。
session是保存在服务端。session的运行依赖于session-id,而session-id保存在cookie中。
https协议
URL编码指的是对网址上的不安全的字符,例如中文,进行编码,编码后的中文方便在网络上传输,反之为解码。
容易扩展和维护
提高代码的复用性
提高代码可用性
增加代码的可理解性。
封装:对外部隐藏私有的属性和行为,只对外提供一些访问接口。
好处:
- 良好的封装能够减少耦合。
- 类内部的结构可以自由修改。
- 可以对成员变量进行更精确的控制。
- 隐藏信息,实现细节。
多态指一个行为可以有多种表现形式。可以理解为一个功能接口的不同实现。
在Java中,一个类可以继承另一个类的“所有”属性和方法。注意是继承所有的属性和方法了,但是由于每个属性或者方法的修饰符不同,有些属性和方法就访问不到。
抽象是指从具体事物抽出、概括出它们共同的方面、本质属性与关系等,而将个别的、非本质的方面、属性与关系舍弃。在Java中用类来描述抽象的事物,在类里声明它的属性,行为等。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。