jre是java运行环境的意思,包含java虚拟机和java类库,是使用java语言编写程序是所需要的软件环境
jdk是java开发工具包,是程序员使用java语言编写java程序时所用到的开发包
可以总结一句话,jdk和jre,一个用于开发一个用于运行
==是一个比较运算符,基本数据类型比较的是值,引用数据类型比较的是地址
equals是一个方法,只能比较引用数据类型,重写前比较的是地址值,重写后比较的是属性的值
不一定为true。正常情况下,因为equals()方法比较的就是对象在内存中的值,如果值相同,那么Hashcode值也应该相同。但是如果不重写hashcode方法,就会出现不相等的情况。
用于装饰类,类属性,类方法
对于被final修饰的类属性而言,子类就不能给它重新赋值,如果重新赋值,会报错
-1
不是, String是一个对象
基础的数据类型有
int,short,long,char,boolean,float,double,byte,
对应的基本类型的包装类:
Integer,Short,Long,Character,Float,Double,Byte
String字符串的各种操作:
1)获取 length,charAt,indexOf
2)判断 contains,isEmpty,startsWith,endsWith,equals
3) 转换 copyValueOf
4)替换 replace
5)切割 split
6)子串 subString
7)转换,去空隔,比较 toUpperCase,trim,顺序比较
不一样,前一个是常量,后者又重新new了一个对象,内存空间不一样
1)递归方法
2)通过charAt返回char进行字符串的拼接
3) 将字符串转换成字符数组倒叙拼接然后返回值
4)调用StringBuffer中的reverse StringBuffer(s).reverse().toString()
5)把字符串转换成字符数组首位对调位置
equals,length,concat,charAt,substring,codePointAt,indexOf。。。。。。
抽象类不一定要有抽象方法但有抽象方法的类一定是抽象类
1)抽象类不能被实例化
2)抽象类可以有构造函数,被继承时子类必须继承父类一个构造方法,抽象方法不能被声明为静态
3)抽象方法只需声明,无需实现,可以允许普通方法有主体
4)含抽象方法的类必须声明为抽象类
5)抽象的子类必须实现抽象类中所有抽象方法,否则这个子类也是抽象类
final关键字不能用来修饰抽象类额接口
1)抽象类和接口都不能直接实例化,如果要实例化,抽象类变量必须实现所有抽象方法的子类对象,接口变量必须指向实现所有接口方法的类对象
2)抽象类要被子类继承,接口要被类实现
3)接口只能做方法申明,抽象类中可以做方法申明,也可以做方法实现
4)接口里定义的变量只能是公共的静态的常量,抽象类中的变量是普通变量
5)抽象类中的抽象方法必须全部被子类实现,如果子类不能实现全部父类抽象方法,那么该子类只能是抽象类。同样,一个实现接口的时候,如果不能全部实现接口方法,那么该类也只能为抽象类
6)抽象方法只能申明,不能实现,接口是设计的结果,抽象类是重构的接果
7)抽象类里可以没有抽象的方法
8) 如果一个类里又抽象方法,那么这个类只能是抽象类
9)抽象方法要被实现,不能是静态的,也不能是私有的
10)接口可以继承接口,并可多继承接口,但类只能单根继承
根据处理数据类型不同:字符流和字节流
根据数据流向不同:输入流和输出流
BIO和NIO是两种不同的网络通信模型,如今NIO已经大量应用再Jetty、zookeeper、Netty等开源框架中
BIO适用于连接数目比较小,并且一次发送大量数据的场景,这种方式对服务器资源要求比较高,并发局限于应用中
NIO服务器需要支持超大量的长时间连接。比如10000个连接以上,并且每个客户端并不会频繁地发送太多数据。
BIO:同步阻塞 NIO:同步非阻塞 AIO异步非阻塞
创建:createNewFile,mkdir,mdirs
删除:delete,deleteOnExit
判断:exists,isFile,isDirectory,isHidden,isAbsolute
获取:getName,getAbsolutePath,length,getParent,lastModified
文件夹相关 startic File
数组,String,java.util下的集合容器
java.util.collection是一个集合接口,提供对集合对象进行基本操作的通用接口的方法
Collections是集合类的一个工具类(辅助类),提供一系列的静态方法,用于对集合中的元素进行排序、搜索以及线程安全各项操作。
list:有序可以重复,可以插入多个null元素
Set:无序不可以重复,只允许有一个null元素
map:不是collection的子接口或者实现类,推行键值对,一个key一个value
1)HashMap和HashTable都实现了map的接口,主要区别在于线程安全性、同步以及速度
2)Hashmap是非同步的,而hashtable是同步的,意味着哈市table是线程安全的,多个线程可以共享一个hashtable
3)Hashmap的迭代器是fail-fast迭代器,而hashTable不是
4)Hashtable在单线程的环境下要比hashmap要慢;如果不需要同步,在单线程环境下,使用hashmap性能比hashtable好
5)Hashmap不能保证随着时间的推移map中的元素次序是不变的
Hashmap通过hascode对其内容进行查找,TreeMap所有的元素都保持某种固定的顺序,
HashMap由数据和链表组成,数组是hashmap的主体,链表主要是解决哈希冲突而存在的,如果定位到的数组位置不含链表,那么对于查找,添加等操作很快,仅需一次寻址即可;如果定位到的数组包含链表,对于添加操作,其时间复杂度为o,首先遍历链表,存在即覆盖;对于查找操作来讲,还需遍历链表,然后通过key对象的equals方法逐一比对查找。所以,性能考虑,HashMAp中的链表出现越少,性能才会越好。
1 HashMap由数据和链表组成
2 链表主要是解决哈希冲突而存在的 对于查找,添加等操作很快
3 通过key对象的equals方法逐一比对查找,HashMAp中的链表出现越少,性能才会越好
iterator:返回对此set中元素进行迭代的迭代器
size:返回此set中元素的数量(set的容量)
isEmpty:判断Hashset集合是否为空
contains:判断某个元素是否存在于HashSet中
add():如果此set中尚未包含指定元素,则添加指定元素
ArrayList使用了数组的实现,封装了对内部数组的操作
linkedList使用了循环双向链表数据结构
list转数组:toArray(arraylist.size)方法
数组转list:Arrays的asList(a)的方法
1)Vector的方法都是同步的,是线程安全的,而ArrayList的方法不是,由于线程同步必然影响性能,因此,ArrayList的性能比Vector好
2)当Vector或ArrayList的元素超过它的初始大小时,Vector会将它的容量翻倍,而ArrayList只增加50%的大小,这样,ArrayList就有利于节约内存空间。
1 Vector的方法都是同步的,是线程安全的 ArrayList的方法不是
2 Vector会将它的容量翻倍,ArrayList只增加50%的大小
1)ArrayList是Array的复杂版本
2)ArrayList可以存储异构对象,而Array只能存储相同类型的数据 [1,a,true] [1,2,3,4]
3)Array的长度实际上是不可变的,二维变长数组实际上的长度也是固定的,可变的是其中元素的长度而ArrayList的长度可以指定也可以不指定,是变长的
4)存取和增删的不同
remove和poll方法都是删除队列的头元素,remove方法在队列为空的情况下将抛出异常,而poll方法将返回null
Vector,HashTable,ConcurrentHashMap,Stack
为各种容器提供了公共的操作接口,使得对容器的遍历操作与其具体的底层实现相隔离,达到解耦的效果。
Iterator的常用方法:
1.boolean hasNext()
2.Object next()
3.void remove()
4.void forEachRemaining(Consumer action)
Iterator的特点:
遍历过程:
1.不允许线程对集合元素进行修改,否则会抛出异常
2.可以通过remove方法来移除集合中的元素
3.Iterator必须依附某个Collection对象而存在,本身不具有装载数据对象的功能
4.Iterator.remove方法删除的是上一次Iterator.next()方法返回的对象
5.强调以下next()方法,该方法通过游标指向的形式返回Iterator下一个元素
1.iterator()方法在set和list接口中都有定义,但li's'tIterator()仅存在于list接口中(或者实现类中)
2.listIterator有add()方法,可以向list中添加对象,而Iterator不能
3.两个都有hasNext()和next()方法,可以实现顺序向后遍历,但listIterator有hasPrevious()和previous()方法,可以实现逆向遍历,Iterator就不可以。
4.listIterator可以定位当前的索引位置,nextIndex()和previousIndex()可以实现,Iterator没有此功能
5.都可以实现删除对象,但listIterator可以实现对象的修改,set方法可以实现,Iterator仅能遍历,不可以修改
将参数中的List返回一个不可修改的List
并发:指应用能够交替执行不同的任务,其实并发有点类似于多线程的原理
并行:指应用能够同时执行不同的任务。
主要区别在于它们是不同的操作系统资源管理方式。
1)一个程序至少有一个进程,一个进程至少有一个线程
2)线程的划分尺度小于进程,使得多线程程序的并发性高
3)进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而大大地提高了程序的运行效率
4)每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口。但线程不能够独立执行,必须依存于应用程序中,由应用程序提供多个线程执行控制。
5)多线程的意义在于一个应用程序中,有多个执行部分可以同时执行,但操作系统并没有将多个线程看做多个独立的应用,来实现进程的调度和管理以及资源分配。
守护线程,是一个服务线程,准确的来说是服务其他的线程,另一个线程是用户线程
守护线程如垃圾回收线程
用户线程就是应用程序里的自定义线程
继承Thread类
实现runable接口
最大的不同点:实现Callable接口的任务线程能返回执行结果,而实现runable接口的任务线程不能返回结果
Callable接口的call()方法允许抛出异常,而Runable接口的run()方法的异常只能在内部消化,不能继续上抛.
1.新建状态
2.就绪状态
3.运行状态
4.阻塞状态
5.死亡状态
对于sleep()方法,是属于Thread类,而wait()方法属于Object类
调用sleep()方法时,线程不会释放对象锁,而调用wait()方法时,线程会放弃对象锁,进入此对象的等待锁定池,只有针对此对象调用nofity()方法后本线程才进入对象锁定池准备
notifyAll():唤醒所有wait线程 notify:只随机唤醒一个wait线程
run()相当于线程的任务处理逻辑入口方法,由java虚拟机在运行相应线程时直接调用,而不是由应用代码进行调用
start()的作用是启动相应的线程。start()调用结束并不表示相应的线程已经开始,这个线程可能稍后运行,也有可能永远也不会运行
1.newCachedThreadPool
2.newFixedThreadPool
3.newSingleThreadExecutor
4.newSingleThreadScheduledExecutor和newScheduledThreadPool(int corePoolSize)
5.newWorkStealingPool
Running、ShutDown、Stop、Tidying、Terminated
1.接收的参数不一样
2.submit有返回值,而execute没有
3.submit方便Exception处理
线程的安全性体现在三个方面:原子性,可见性,有序性
在java中锁共有4种状态,由低到高依次为无状态锁,偏向锁,轻量级锁和重量级锁状态,这几个状态会随着竞争情况升级。锁可以升级但不能降级。
指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。
1.加锁顺序 2.加锁时限 3.死锁检测
ThreadLocal叫做线程本地变量,也有叫做线程本地存储,即为变量在每个线程中创建了一个副本,每个线程可以访问自己内部的副本变量
最常见的ThreadLocal使用场景为用来解决数据库连接、session管理等
方法级的同步是隐式,即无需通过字节码指令来控制的,它实现在方法调用和返回操作之中。jvm可以从方法常量池中的方法表结构中的ACC_SYNCHRONIZED访问标志区分一个方法是否是同步方法。当方法调用时,调用指令将会检查方法的ACC_SYNCHRONIZED访问标志是否被设置,如果设置了,执行线程将先持有monitor,然后再执行方法,最后在方法完成时释放monitor。在方法执行期间,执行线程持有了monitor,其他任何线程都无法再获得同一个monitor。如果一个同步方法执行期间抛出了异常,并且在方法内部无法处理此异常,那这个同步方法所持有的monitor将在异常抛到同步方法之外时自动释放。
1.同步 过字节码指令来控制
2.jvm 从方法常量池中 访问标志区分一个方法是否是同步方法 调用指令 检查方法的ACC_SYNCHRONIZED访问标志是否被设置
3.获取锁,其他线程无法获取锁
*首先synchronized是java内置关键字,在jvm层面,lock是个java类
*synchronized无法判断是否获取锁的状态,lock可以判断是否获取到锁
*synchronized会自动释放锁,lock需在finally中手工释放锁,否则容易造成线程死锁
*用sychronized关键字的两个线程1和线程2,如果当前线程1获得锁,线程2等待。如果线程1阻塞,线程2会一直等待下去,而Lock锁就不一定会等待下去,如果尝试获取不到锁,线程可以不用一直等待就结束了
*synchronized的锁可重入、不可中断、非公平,而Lock锁皆可实行
*Lock锁适合大量同步的代码的同步问题,synchronized锁适合代码少量的同步问题
这两种方式最大区别就是对于Synchronized来说他是java语言的关键字,是原生语法层面的互斥,需要jvm实现。而reemntrantLock它是jDK1.5之后提供的API层面的互斥锁,需要lock()和unlock()方法配合try/finally语句块来完成。
使用atomic修饰属性,编译器会设置默认读写方法为原子读写,并使用互斥锁添加保护。
指运行中的程序检查自己和软件运行环境的能力,他可以根据它发现的进行改变。通俗的讲就是反射可以在运行时根据指定的类名获得类的信息。
是一种用来处理对象流的机制,对象流也就是将对象的内容进行流化,将数据分解成字节流,以便存储在文件中或在网络中传输。
情况:1.对象序列化可以实现分布式对象
2.java对象序列化不仅保留一个对象的数据,而且递归保存对象引用的每一个对象的数据
当想要给实现了某个接口的类中的方法,加一些额外的处理,比如加日志,加事务,加权限,Spring的AOP等。
首先必须定义一个接口,还要有一个InvocationHandler处理类。再有一个工具类Proxy。利用到InvacationHandler,并接代理类源码,将其编译生成代理类的二进制码,利用机器加载,并将其实例化产生代理对象,最后返回
想对一个对象进行处理,又想保留原有的数据进行接下来的操作,就需要克隆了。
两种不同的克隆方式,浅克隆(ShallowClone)和深克隆(DeepClone)
两种方式:实现Cloneable接口并重写object类中的clone()方法
实现Serializable接口,通过对象的序列化和反序列化实现克隆,可以实现真正的深度克隆
浅克隆只是复制了对象的引用地址,两个对象指向同一个内存地址,所以修改其中任意的值,另一个值都会随之变化,这就是浅拷贝
深拷贝是将对象及值复制过来,两个对象修改其中任意的值另一个值不会改变,这就是深拷贝
jsp的本质是servlet,jvm只能识别java类,不能识别jsp的代码,web容器将jsp的代码编译成jvm额能够识别的java类
jsp更擅长表现于页面显示,servlet更擅长于逻辑控制
Servlet中没有内置对象,jsp的内置对象都是通过HTTPServletRequest对象,HttpServletREsponse对象以及HttpServlet对象得到的
jsp是Servlet的一种简化,使用jsp只需完成程序员需要输出到客户端的内容,jsp中的java脚本如何镶嵌到一个类中,youjsp容器完成
page:指的是JSP被翻译成Servlet的对象的引用
pageContext:对象可以用来获得其他8个内置对象,还可以作为Jsp的域范围对象使用
request:代表的是请求对象,可以用于获得客户机的信息,也可以作为域对象使用,使用request保存的数据在一次请求范围内有效
Session:代表的是一次会话,可以用来保存用户的私有信息,也可以作为域对象使用,使用session保存的数据在一次会话范围有效
Application:代表整个应用范围,使用这个对象保存的数据在整个web应用中都有效
Response:是响应对象,代表的是从服务器向浏览器响应数据
Out:jspWrite是用于向页面输出内容的对象
Config:指的是ServletConfig用于JSP翻译成Servlet后获得Servlet的配置的对象
Exception:在页面设置isErrorPage=“true”,即可使用,是Throwable的引用,用来获得页面错误的信息
page,request,session,application
1.Cookie以文本文件格式存储在浏览器中,而session存储在服务器端它存储了限制数据量。它只允许4kb他没有在cookie中保存多个变量
2.cookie的存储限制了数据量,只允许4kb,而session是无限量的
3.我们可以轻松地访问cookie值但是我们无法轻松访问会话值,因此它更安全
4.设置cookie时间可以使cookie过期,但是使用session-destory(),将会销毁会话
当打开浏览器到关闭浏览器,这一期间称为一个会话,也就是一个session,是保存在服务器端的,每当客户端请求页面时,服务器就会自动分配一个ID来唯一识别这个用户。一般不用session来保存大量的数据,这样会占用大量的资源。
在Asp中,Session必须依赖Cookie才可用,session是存储在服务器端的,而Cookie是存储在客户端的,相对而言,session的那全性和可靠性程度都比cookie高
在Php中通过相关额配置,可以让session不依赖Cookie而存在
1.底层实现机制:struts2是filter springmvc是servlet
2.运行效率:struts2底层是Servlet,参数基于属性封装,如果配置单例,会出现线程安全问题,所以配置多例
springmvc底层是servlet,单例
3.参数封装:struts2基于属性封装
springMvc基于方法进行封装
1.检查变量数据类型和格式
2.过滤特殊字符
3.绑定变量,使用预编译语句
总结:使用预编译绑定变量的sql语句
严格加密处理用户的机密信息
不要随意开启生产环境中的webserver的错误信息
使用正则表达式过滤传入的参数
字符串过滤
检查是否包含非法字
即跨站脚本攻击,是一种常见于web应用于web应用程序中的计算机安全漏洞
1.获取用户输入,不用.innerHtml,用innerText
2.对用户输入进行过滤,如HtmlEncode函数实现应该至少进行&<>"’/等符号转义成&It>"'/
即跨站请求伪造
1.请求令牌
2.token验证
3.配置angular提交表头
4.再次测试跨域post
异常
1.throw是在代码块内的,即在捕获方法内的异常并抛出时用的
try{} cacth(Exce e){ throw new Exc()}
2.throws是针对方法的,即将方法的异常信息抛出去
void main() throws Ex
3.可以理解为throw是主动的,而throws是被动的
final:用来修饰类,方法和变量
finally:作为异常的处理部分,只能在try/catch语句中,表示这段语句最终一定会被执行
finalize:是在java.lang.Object里定义的,也就是说每一个对象都有这么个方法,该对象被回收时被调用。
try语句后面必须要有一个别的语句跟在后面,如try-catch,try-finally,try-catch-finally
会执行,在return前执行
IOEException、RunntimeException、ArrayIndexOUtOfBoundsException、NullpointerException
301,302都是Http状态的编码,都代表着某个URL发生了转移
区别: 301 redirect:代表永久性转移
302 redirect:代表暂时性转移
代表了两种请求转发方式:直接转发(forward)和间接转发(redirect)
举例:直接:A找B借钱,B说没有,B去找C借,借到借不到都会把信息传递给A
简接:A找B借钱,B说没有,让A去找C借
1.基于连接与无连接
2.对于系统资源的要求(TCP较多,UDP少)
3.UDP程序结构较为简单
4.流模式与数据包模式
5.TCP保证数据正确性,UDP可能丢包,TCP保证数据顺序,UDP不保证
不行,因为为了防止已失效的连接请求又传送到服务器端,因而产生错误
要发送的数据小于TCP发送缓冲区的大小,TCP将多次写入缓冲区的数据一次发送出去,将会发生粘包
接收数据端的应用层没有及时读取接收缓冲区中的数据,将会发生粘包
应用层,表示层,会话层,传输层,网络层,数据链路层,物理层
Get:从指定的资源请求数据
post:向指定的资源提交要被处理的数据
1.图片ping或script标签跨域
2.JSONP跨域
3.CORS
4.window.name+iframe
5.window.postMessage()
6.修改document.domain跨子域
7.WebSocket
8.代理
浏览器只对XHR请求有同源请求限制,而对script标签src属性、link标签ref属性和img标签src属性没有这种限制,利用这个“漏洞”就可以很好的解决跨域请求。JSONP就是利用了script标签无同源限制的特点来实现的,当向第三方站点请求时,我们可以将此请求放在