Java常见知识记录(二)

Java反射

1 反射机制fsh
·概念:就是运行时动态的获取类的信息和操作类的方法和属性
·获取Class对象方法:class.getClass(),Class.forName,ClassLoader.loadClass
·Class类方法:
getClassLoader,forName,getdeclareemethod,getdeclaredfield,getconstructor(declared可以获取所有方法,不只获取public方法)。
2 Class.forName和classloader.loadClass的区别
·forname在类加载的时候会执行静态代码块
·loadclass只有在调用newInstance方法的时候才会执行静态代码块
·初始化不同:Class.forName()会对类初始化,而loadClass()只会装载或链接
·类加载器不同:Class.forName(String)方法(只有一个参数),使用调用者的类加载器来加载,也就是用加载了调用forName方法的代码的
那个类加载器。相应的,ClassLoader.LoadClass()方法是一个实例方法(非静态方法),调用时需要自己制定类加载器。

static方法是否可以覆盖?
static方法不能被覆盖,因为方法覆盖是基于运行时动态绑定的,而static方法是编译时静态绑定的。static方法跟类的任何实例都不相关,所以
概念上不适用。

注意:静态变量,静态代码块先执行,静态的东西只执行一次,相当于全局变量。

session和cookie的区别
·session在服务器端,cookie在客户端(浏览器)
·session的运行依赖session id,而session id是存在cookie中的,也就是说,如果浏览器禁用了cooike,同时session也会失效(但是可以通过
其它方式实现,比如在url中传递session_id)
·session可以放在文件,数据库,或内存中都可以。
·用户验证这种场合一般会用session
·cookie不是很安全,别人可以分析存放在本地的cookie并进行cookie欺骗,考虑到安全应当使用session
·session会在一定时间内保存在服务器上,当访问增多,会比较占用你服务器的性能,考虑到减轻服务器性能方面,应当使用cookie。
·单个cookie保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20个cookie。

IO NIO BIO AIO select epoll
·BIO
·同步并阻塞,服务器实现模式为一个链接一个线程,即客户端有连接请求时服务器端就需要启动一个线程进行处理,如果这个链接不做任何事
情会造成不必要的线程开销,当然可以通过线程池机制改善。
·BIO方式使用于连接数目比较小且固定的架构,这种方式对服务器资源要求比较高,并发局限于应用中,JDK1.4以前的唯一选择,但程序直观简单
易理解。
·NIO
·同步非阻塞,服务器实现模式为一个请求一个线程,即客户端发送的连接请求都会注册到多路复用器上,多路复用器轮询到连接有I/O请求时才启动
一个线程进行处理。
·NIO方式适用于连接数目多且连接比较短(轻操作)的架构,比如聊天服务器,并发局限于应用中,编程比较复杂。
·AIO
·异步非阻塞,服务器实现模式为一个有效请求一个线程,客户端的I/O请求都是由OS先完成了再通知服务器应用去启动线程进行处理。
·AIO方式使用于连接数目多且连接比较长(重操作)的架构,比如相册服务器,充分调用OS参与并发操作,编程比较复杂,JDK7开始支持。

os(select/epoll)区别–IO多路复用

IO多路复用的机制,多路复用是同步非阻塞I/O,即Synchronous I/O数据,则启动相应的Application处理,在select和poll找那个利用轮询socket
句柄的方式来实现监测socket中是否有I/O数据到达,这种方式有开销,epoll等则改进了这种方式,利用底层notify机制,即Reactor方式来监测,
Java NIO也是采用这种机制。这里需要注意,其实多路复用还是有阻塞的(这个阻塞并非以上定义的阻塞,这里指socket无I/O数据时还是被wait,
此外当时用select函数copy I/O数据入Application Buffer时,Application还是被阻塞的)

select和epoll区别:
1、每次调用select,都需要吧fd集合从用户态拷贝到内核态,这个开销在fd很多时会很大
2、同时每次调用select都要在内核遍历传递进来的所有fd,这个开销在fd很多时也很大
3、select支持的文件描述符数量太小了,默认是1024
4、epoll为每个fd指定一个回调函数,当设备就绪,唤醒等待队列上的等待着时。就会调用这个回调函数
5、epoll多支持的fd上线是最大可以打开文件的数目。

poll 它没有最大连接数的限制,原因是它是基于链表来存储的,但是同一样有一个缺点:大量的fd的数组被整体复制与用户态和内核地址空间之间,
而不管这样的复制是不是有意义。

协程:看上去也是子程序,但执行过程中,在子程序内部可中断,然后转而执行别的子程序,在适当的时候再返回来接着执行。

什么是阻塞和非阻塞,什么是同步和异步。
同步和异步是针对应用程序和内核的交互而言的,同步指的是用户进程触发IO操作并等待或者轮询的去查看IO操作是否就绪,而异步是指用户进程
触发IO操作以后便开始做自己的事情,而当IO操作已经完成的时候会得到IO完成的通知。
而阻塞和非阻塞是针对于进程在访问数据的时候,根据IO操作的就绪状态来采取的不同方式,说白了是一种读取或者写入操作函数的实现方式,
阻塞方式下读取或者写入函数将一直等待,而非阻塞方式下,读取或者写入函数会立即返回一个状态值。

一般来说I/O模型可以分为:同步阻塞,同步非阻塞,异步阻塞,异步非阻塞IO

同步阻塞IO:在此种方式下,用户进程在发起一个IO操作以后,必须等待IO操作的完成,只有当真正完成了IO操作以后,用户进程才能运行。JAVA传统的IO模型属于此种方式。
同步非阻塞IO:在此种方式下,用户进程发起一个IO操作以后可返回做其它事情,但是用户进程需要时不时的询问IO操作是否就绪,这就要求用户
进程不同的去询问,从而引入不必要的CPU资源浪费。其中目前JAVA的NIO就属于同步非阻塞IO。
异步阻塞IO:此种方式下是指应用发起一个IO操作以后,不等待内核IO操作的完成,等内核完成IO操作以后会通知应用程序,这其实就是同步和异步
最关键的区别,同步必须等待或者主动的去询问IO是否完成,那么为什么说是阻塞的呢?因为此时是通过select系统调用来完成的,而select函数本身的
实现方式是阻塞的,而采用select函数有个好处就是它可以同时监听多个文件句柄,从而提高系统的并发性。
异步非阻塞IO:在此种模式下,用户进程只需要发起一个IO操作然后立即返回,等IO操作真正的完成以后,应用程序会得到IO操作完成的通知,
此时用户进程只需要对数据进行处理就好了,不需要进行实际的IO读写操作,因为真正的IO读取或者写入操作已经由内核完成了。

JavaNIO和IO的主要区别
1、Java NIO和IO之间第一个最大的区别是,IO是面向流的,NIO是面向缓冲区的。
2、Java IO的各种流是阻塞的。这意味着,当一个线程调用read()或write()时,该线程被阻塞,直到有一些数据被读取
Java NIO的非阻塞迷死,使一个线程从某通道发送请求读取数据,但是它仅能得到目前可用的数据,如果目前没有数据可用时,就什么都不会获取。
3、Java NIO的选择器允许一个单独的线程来监视多个输入通道。

Threadlocal
Threadlocal不是解决对象的共性访问问题,通过ThreadLocal.set()到线程中的对象是该线程自己使用的对象,其它线程是不需要访问的,也访问
不到的。各个线程中访问的是不同的对象。
各个线程独立的对象不是通过Threadlocal.set创建的,而是在每个线程new的对象。Threadlocal.set将创建对象的引用保存到线程独有的map中,
当有其他线程对这个引用指向的对象做修改时,当前线程Thread对象中保存的值也会发生变化。
当时用ThreadLocal维护变量时,ThreadLocal为每个使用该变量的线程提供独立的变量副本,所以每个线程都可以独立的改变自己的副本,而不会
影响到其它线程所对应的副本。

finalize finalization finally
一、finalize用途
垃圾回收器决定回收某对象时,就会运行该对象的finalize()方式,但是在java中和不幸,如果内存总是充足的,那么垃圾回收可能永远不会
记性,也就是说finalize()可能永远不被执行,显然指望它做收尾工作是靠不住的。finalize()最主要的用途是回首特殊渠道申请的内存。java程序
有垃圾回收器,所以一般情况下内存不用程序员操心,但有一种JNI(Java Native Interface)调用non-Java程序(C或C++),finalize()的工作
就是回收这部分的内存。
二、finally
Try catch finally
在try中return之前会执行finally中的代码,如果finally中有return则直接return,值为finally中修改的;
如果finally中没有return,则执行try中的return,数值仍然是try中的。
finally一定会被执行,如果finally里有return语句,则覆盖try/catch里的return。
比较爱考的是finally里没有return语句,这时虽然finally里对return的值进行了修改,但return的值并不改变这种情况

finally代码块和finalize()方法有什么区别?
无论是否抛出异常,finally代码块都会执行,它主要是用来释放应用占用的资源。finalize()方法是Object类的一个protected方法,它是在对象
被垃圾回收之前有Java虚拟机来调用的。

equals和 == 的区别
基本数据类型用( == )进行比较的时候,比较的是实际值
复合数据类型,(==)比较的是他们在内存中的存放地址
String,Integer,data等重写了equal,比较的是内容。没有重写equal的,比较的还是内存地址

StringBuffer和StringBuilder特殊,==和equal都是比较地址

Java中的两种异常类型是什么?他们有什么区别?
Java中有两种异常:受检查的异常和不受检查的异常。不受检查的异常不需要在方法或者是构造函数上声明,就算方法或者是构造函数的执行可
能会抛出这样的异常,并且不受检查的异常可以传播到方法或者是构造函数的外面。相反,受检查的异常必须要用throws语句在方法或者是构造函数
上声明。

throw和throws有什么区别?
throw和throws关键字用来在程序中明确的抛出异常,相反,throws语句用来表明方法不能处理的异常。每一个方法都必须要指定那些异常不能
处理,所以方法的调用者才能够确保处理可能发生的异常,多个异常使用逗号分隔的。

java提供了两种异常机制。一种是运行时异常,一种是检查式异常
检查式异常:我们经常遇到的IO异常及sql异常就属于检查式异常。对于这种异常,java编译器要求我们必须对出现的这种异常进行catch,所以
面对这种异常不管我们是否愿意,只能自己去写一堆catch来捕捉这些异常,
运行时异常:我们可以不处理。当出现这样的异常时,总是由虚拟机接管,比如:我们从来没有人去处理过NullPointerException异常,它就是
运行时异常,并且这种异常还是最常见的异常之一。

·Throwable是java语言中所有错误和异常的超类(万物皆可抛)。它有两个子类:Error,Exception。
·异常种类
·Error:Error为错误,是程序无法处理的,如OutOfMemoryError等,出现这种情况你唯一能做的就是听之任之,交由JVM来处理,不过JVM在大
多数情况下会选择终止线程。
·Exception:Exception是程序可以处理的异常,它又分为两种:CheckedException(受检异常),UnCheckedException(不受检查异常)。
·CheckedException发生在编译阶段,必须要使用try…catch(或者throws),否则编译不通过。
·UncheckedException发生在运行期,具有不确定性,主要是由于程序的逻辑问题所引起的,难以排查,我们一般都需要纵观全局才能够发
现这类的异常错误,所在在程序设计中我们需要认真考虑,好好写代码,尽量处理异常,即使产生了异常,也能尽量保证程序朝着有利方向
发展。
·常见异常的基类
·IOException
·RuntimeException

·java序列化定义
·将那些实现了Serialzable接口的对象转换成一个字节序列,并能够在以后将这个字节序列完全恢复为原来的对象,序列化可以弥补不同操作
系统之间的差异。
·java序列化的作用
·java远程方法调用(RMI)
·对JavaBean进行序列化
·如何实现序列化和反序列化
·实现序列化方法
·实现Serializable接口
·该接口知识一个可序列化的标签,并没有包含实际的属性和方法。
·如果不在改方法中添加readObject()和writeObject()方法,则采取默认的序列化机制。如果添加了这两个方法之后还想利用Java默
认的序列化机制,则在这两个方法中分别调用defaultReadObject()和defaultWriteObject()两个方法。
·为了保证安全性,可以使用transient关键字进行修饰不必序列化的属性。因为在反序列化时,private修饰的属性也能查看到。
·实现ExternalSerializable方法
·自己对要序列化的内容进行控制,控制哪些属性能被序列化,哪些不能被序列化。
·反序列化
·实现Serializable接口的对象在反序列化时不需要调用对象所在类的构造方法,完全基于字节。
·实现externalSerializable接口的方法在反序列化时会调用构造方法。
注意事项
·被static修饰的属性不会被序列化
·对象的类名。属性都会被序列化,方法不会被序列化
·要保证序列化对象所在类的属性也是可被序列化的。
·当通过网络、文件进行序列化时,必须按照写入的顺序读取对象。
·反序列化时必须有序列化对象时的class文件
·最好显示的声明serializableID,因为在不同的JVM之间,默认生成serializable可能不同,会造成反序列化失败。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值