多态:
多态是指程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编程时并不确定,而是在程序运行期间才确定,即一个引用变量倒底会指向哪个类的实例对象,该引用变量发出的方法调用到底是哪个类中实现的方法,必须在由程序运行期间才能决定。因为在程序运行时才确定具体的类,这样,不用修改源程序代码,就可以让引用变量绑定到各种不同的类实现上,从而导致该引用调用的具体方法随之改变,即不修改程序代码就可以改变程序运行时所绑定的具体代码,让程序可以选择多个运行状态,这就是多态性。多态性增强了软件的灵活性和扩展性。例如,下面代码中的UserDao是一个接口,它定义引用变量userDao指向的实例对象由daofactory.getDao()在执行的时候返回,有时候指向的是UserJdbcDao这个实现,有时候指向的是UserHibernateDao这个实现,这样,不用修改源代码,就可以改变userDao指向的具体类实现,从而导致userDao.insertUser()方法调用的具体代码也随之改变,即有时候调用的是UserJdbcDao的insertUser方法,有时候调用的是UserHibernateDao的insertUser方法。
多态是指程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编程时并不确定,而是在程序运行期间才确定,即一个引用变量倒底会指向哪个类的实例对象,该引用变量发出的方法调用到底是哪个类中实现的方法,必须在由程序运行期间才能决定。因为在程序运行时才确定具体的类,这样,不用修改源程序代码,就可以让引用变量绑定到各种不同的类实现上,从而导致该引用调用的具体方法随之改变,即不修改程序代码就可以改变程序运行时所绑定的具体代码,让程序可以选择多个运行状态,这就是多态性。多态性增强了软件的灵活性和扩展性。例如,下面代码中的UserDao是一个接口,它定义引用变量userDao指向的实例对象由daofactory.getDao()在执行的时候返回,有时候指向的是UserJdbcDao这个实现,有时候指向的是UserHibernateDao这个实现,这样,不用修改源代码,就可以改变userDao指向的具体类实现,从而导致userDao.insertUser()方法调用的具体代码也随之改变,即有时候调用的是UserJdbcDao的insertUser方法,有时候调用的是UserHibernateDao的insertUser方法。
sleep()和wait()方法的区别
1.sleep()是线程暂停执行一段时间,把cpu资源让出来给其他线程执行,这个期间,这个线程的状态依然保持,等到设定的时间一到,该线程就自动苏醒,继续执行。
2.wait()方法是object类的方法,它用于线程间的通信,这个方法会使当前拥有对象锁的进程等待,直到其他线程调用notify()或notifyAll()方法,它才会自动醒来。
3.sleep()方法不会释放锁,调用wait()方法会释放掉它所占用的锁,从而使线程所在对象中的其他synchronized数据可以被别的线程使用。
4.sleep()必须捕获异常,可以在任何地方使用,wait()方法只能在同步控制方法或代码块里使用。
1.sleep()是线程暂停执行一段时间,把cpu资源让出来给其他线程执行,这个期间,这个线程的状态依然保持,等到设定的时间一到,该线程就自动苏醒,继续执行。
2.wait()方法是object类的方法,它用于线程间的通信,这个方法会使当前拥有对象锁的进程等待,直到其他线程调用notify()或notifyAll()方法,它才会自动醒来。
3.sleep()方法不会释放锁,调用wait()方法会释放掉它所占用的锁,从而使线程所在对象中的其他synchronized数据可以被别的线程使用。
4.sleep()必须捕获异常,可以在任何地方使用,wait()方法只能在同步控制方法或代码块里使用。
heap和stack的区别
1.栈主要存取的是基本数据类型和引用类型,存取速度比较快,但是栈的大小和生命周期必须是确定的,它是通过压栈和弹栈管理栈内存。
2.堆主要存取的是运行时创建的对象,堆可以动态的分配内存,生命周期不用提前告诉编译器,存取速度比较慢,它是通过垃圾回收器来自动回收内存。每个java程序都有一个单独的jvm实例,每一个实例都对应一个堆。多线程的情况下,会共享堆内存,所以需要对数据使用同步
1.栈主要存取的是基本数据类型和引用类型,存取速度比较快,但是栈的大小和生命周期必须是确定的,它是通过压栈和弹栈管理栈内存。
2.堆主要存取的是运行时创建的对象,堆可以动态的分配内存,生命周期不用提前告诉编译器,存取速度比较慢,它是通过垃圾回收器来自动回收内存。每个java程序都有一个单独的jvm实例,每一个实例都对应一个堆。多线程的情况下,会共享堆内存,所以需要对数据使用同步
不可变类
所谓String类是不可变类,是指这个类定义的变量一旦被初始化便不可改变,这里不可改变的意思对基本类型来说是其值不可变,而对于对象变量来说其引用不可再变,但引用变量所指向的对象中的内容还是可以改变的。
所谓String类是不可变类,是指这个类定义的变量一旦被初始化便不可改变,这里不可改变的意思对基本类型来说是其值不可变,而对于对象变量来说其引用不可再变,但引用变量所指向的对象中的内容还是可以改变的。
http请求过程
1.建立tcp连接
2.web浏览器向web服务器发送请求命令
3.web浏览器发送请求头信息
4.web服务器应答
5.web服务器发送应答头信息
6.web服务器向web浏览器发送数据
7.web服务器关闭tcp连接
1.建立tcp连接
2.web浏览器向web服务器发送请求命令
3.web浏览器发送请求头信息
4.web服务器应答
5.web服务器发送应答头信息
6.web服务器向web浏览器发送数据
7.web服务器关闭tcp连接
string stringBuffer stringBuilder区别
1.string是不可变类,对象创建后,不可以对其修改值。
2.stringBuffer是可变类,对象创建后,仍然可以对其修改值,stringBuffer类是线程安全的
3.stringBuilder是非线程安全的,在单线程下可以使用stringBuilder,
效率上:stringbuilder>stringBuffer>string
1.string是不可变类,对象创建后,不可以对其修改值。
2.stringBuffer是可变类,对象创建后,仍然可以对其修改值,stringBuffer类是线程安全的
3.stringBuilder是非线程安全的,在单线程下可以使用stringBuilder,
效率上:stringbuilder>stringBuffer>string
解耦合
其实最关键的一点是,A 需要 B 对象,但是 B 对象的生命周期不归 A 管,这应该才是解耦的根本吧
假如b和c都是实现Demo这个接口,那么a获取b对象则用getBean("demo",Demo.class),获取到的是Demo接口,现在b这个实现类实现的不完美,我想用Demo的另一个实现类C代替,只需要改配置文件就成了,这样a不必关心Demo怎么实现的,只要做自己的就成了
其实最关键的一点是,A 需要 B 对象,但是 B 对象的生命周期不归 A 管,这应该才是解耦的根本吧
假如b和c都是实现Demo这个接口,那么a获取b对象则用getBean("demo",Demo.class),获取到的是Demo接口,现在b这个实现类实现的不完美,我想用Demo的另一个实现类C代替,只需要改配置文件就成了,这样a不必关心Demo怎么实现的,只要做自己的就成了
解释RMI
1.Spring rmi除了使用基于HTTP协议的远程调用方案,还为开发者提供了基于RMI机制的远程调用方法,RMI远程调用网络通信实现是基于TCP/IP协议完成的,而不是通过HTTP协议。
在Spring RMI实现中,集成了标准的RMI-JRIM解决方案,该方案是java虚拟机实现的一部分,它使用java序列化来完成对象的传输,是一个java到java环境的分布式处理技术,不涉及异构平台的处理。
3.RmiProxyFactoryBean:
RmiProxyFactoryBean的主要功能是对RMI客户端封装,生成代理对象,查询得到RMI的stub对象,并通过这个stub对象发起相应的RMI远程调用请求。
通过对上面RmiProxyFactoryBean源码分析中,我们看到在创建远程调用代理对象的时候需要设置拦截器,因为我们继续分析远程调用客户端拦截器
RmiClientInterceptor。
4.RmiClientInterceptor封装RMI客户端:
RmiClientInterceptor对客户端的远程调用进行拦截,具体的生成远程调用代理对象、查找远程调用stub、以及通过RMI stub向服务端发起远程调用请求的具体实现都由RMI客户端拦截器实现
通过上面对RmiClientInterceptor源码分析,我们看到Spring对RMI远程调用使用以下两种方式:
(1).RMI调用器方式:
这种方式和Spring HTTP调用器非常类似,即使用RemoteInvocation来封装调用目标对象、目标方法、参数类型等信息,RMI服务器端接收到RMI请求之后直接调用目标对象的匹配方法。
(2).传统RMI调用方式:
使用JDK的反射机制,直接调用远程调用stub的方法。
RMI中,基于TCP/IP协议,而不是HTTP协议来实现底层网络通信,由于RMI的网络通信已由Java RMI实现,所以这里不再使用Spring MVC的DispatcherServlet来转发客户端配置的远程调用请求URL,只需要指定RMI的TCP/.IP监听端口和服务导出的名称即可。
6.RmiServiceExporter导出RMI远程调用对象:
RmiServiceExporter主要功能是将服务端远程对象提供的服务导出供客户端请求调用,同时将导出的远程对象和注册器绑定起来供客户端查询
RMI远程调用请求最终由DefaultRemoteInvocationExecutor处理。
8.DefaultRemoteInvocationExecutor处理RMI远程调用请求:
在Spring RMI实现中,集成了标准的RMI-JRIM解决方案,该方案是java虚拟机实现的一部分,它使用java序列化来完成对象的传输,是一个java到java环境的分布式处理技术,不涉及异构平台的处理。
3.RmiProxyFactoryBean:
RmiProxyFactoryBean的主要功能是对RMI客户端封装,生成代理对象,查询得到RMI的stub对象,并通过这个stub对象发起相应的RMI远程调用请求。
通过对上面RmiProxyFactoryBean源码分析中,我们看到在创建远程调用代理对象的时候需要设置拦截器,因为我们继续分析远程调用客户端拦截器
RmiClientInterceptor。
4.RmiClientInterceptor封装RMI客户端:
RmiClientInterceptor对客户端的远程调用进行拦截,具体的生成远程调用代理对象、查找远程调用stub、以及通过RMI stub向服务端发起远程调用请求的具体实现都由RMI客户端拦截器实现
通过上面对RmiClientInterceptor源码分析,我们看到Spring对RMI远程调用使用以下两种方式:
(1).RMI调用器方式:
这种方式和Spring HTTP调用器非常类似,即使用RemoteInvocation来封装调用目标对象、目标方法、参数类型等信息,RMI服务器端接收到RMI请求之后直接调用目标对象的匹配方法。
(2).传统RMI调用方式:
使用JDK的反射机制,直接调用远程调用stub的方法。
RMI中,基于TCP/IP协议,而不是HTTP协议来实现底层网络通信,由于RMI的网络通信已由Java RMI实现,所以这里不再使用Spring MVC的DispatcherServlet来转发客户端配置的远程调用请求URL,只需要指定RMI的TCP/.IP监听端口和服务导出的名称即可。
6.RmiServiceExporter导出RMI远程调用对象:
RmiServiceExporter主要功能是将服务端远程对象提供的服务导出供客户端请求调用,同时将导出的远程对象和注册器绑定起来供客户端查询
RMI远程调用请求最终由DefaultRemoteInvocationExecutor处理。
8.DefaultRemoteInvocationExecutor处理RMI远程调用请求: