面试错题
请问object的hash该怎么设计?
下面是解释最简单的一种hash算法
哈希算法又叫散列算法,是将任意长度的二进制值映射为较短的固定长度的二进制值,这个小的二进制值称为哈希值。它的原理其实很简单,就是把一段交易信息转换成一个固定长度的字符串。
即一个从明文到密文的不可逆映射,只有加密过程,没有解密过程。
无论输入是什么数字格式、文件有多大,输出都是固定长度的比特串。
每个bit就是一位0或者1,256bit就是256个0或者1二进制数字串,用16进制数字表示的话,就是多少位呢?
16等于2的4次方,所以每一位16进制数字可以代表4位bit。那么,256位bit用16进制数字表示,当然是256除以4等于64位。
于是你通常看到的哈希值,就是这样的了:
00740f40257a13bf03b40f54a9fe398c79a664bb21cfa2870ab07888b21eeba8。
易压缩:对于任意大小的输入x,Hash值的长度很小,在实际应用中,函数H产生的Hash值其长度是固定的。
易计算:对于任意给定的消息,计算其Hash值比较容易。
单向性:对于给定的Hash值,要找到使得在计算上是不可行的,即求Hash的逆很困难。在给定某个哈希函数H和哈希值H(M)的情况下,得出M在计算上是不可行的。即从哈希输出无法倒推输入的原始数值。这是哈希函数安全性的基础。
抗碰撞性:理想的Hash函数是无碰撞的,但在实际算法的设计中很难做到这一点。
有两种抗碰撞性:一种是弱抗碰撞性,即对于给定的消息,要发现另一个消息,满足在计算上是不可行的;另一种是强抗碰撞性,即对于任意一对不同的消息,使得在计算上也是不可行的。
高灵敏性:这是从比特位角度出发的,指的是1比特位的输入变化会造成1/2的比特位发生变化。消息M的任何改变都会导致哈希值H(M)发生改变。即如果输入有微小不同,哈希运算后的输出一定不同。
2不可逆加密阿呆:小星,你看这样可以不,我想一个A,经过下面的过程:
1.A+123=B
2.B^2=C
3.取C中第2~4位数,组成一个3位数D
4.D/12的结果求余数,得到E
小星:嗯,我想想,假如阿呆你想的A为5,那么:
5+123=128
128^2=16384
D=638 E=638mod12=53
(mod表示除法的求余数)
这种丢掉一部分信息的加密方式称为“单向加密”,也叫哈希算法
当两个不同的对象计算出相同的散列值时,我们称其为发生了 哈希碰撞 。当出现碰撞时,哈希表会从碰撞产生的位置开始向后寻找,把新的元素放在第一个可供放置的位置,随着哈希表变得越来越致密,发生碰撞的可能性也会随之增加,导致查找可用位置花费的时间也会增加(这也是为什么我们希望哈希函数的结果分布更接近于均匀分布)
http://www.sohu.com/a/232586831_100078137
哈希算法的实现方式很多,有兴趣的自己看吧
数据库三范式
第一范式(1NF):数据表中的每一列(每个字段)必须是不可拆分的最小单元,也就是确保每一列的原子性;
第二范式(2NF):满足1NF后,,没有包含在主键中的列必须完全依赖于主键,不能只依赖于主键的一部分。
第三范式(3NF):必须先满足第二范式(2NF),非主键列必须直接依赖于主键不能存在传递依赖。
spring支持编程式事务管理和声明式事务管理两种方式。
- 编程式事务使用TransactionTemplate或者直接使用底层的PlatformTransactionManager。对于编程式事务管理,spring推荐使用TransactionTemplate。
- 声明式事务是建立在AOP之上的。其本质是对方法前后进行拦截,然后在目标方法开始之前创建或者加入一个事务,在执行完目标方法之后根据执行情况提交或者回滚事务。声明式事务最大的优点就是不需要通过编程的方式管理事务,这样就不需要在业务逻辑代码中掺杂事务管理的代码,只需在配置文件中做相关的事务规则声明(或通过基于@Transactional注解的方式),便可以将事务规则应用到业务逻辑中。
显然声明式事务管理要优于编程式事务管理,这正是spring倡导的非侵入式的开发方式。声明式事务管理使业务代码不受污染,一个普通的POJO对象,只要加上注解就可以获得完全的事务支持。和编程式事务相比,声明式事务唯一不足地方是,它的最细粒度只能作用到方法级别,无法做到像编程式事务那样可以作用到代码块级别。但是即便有这样的需求,也存在很多变通的方法,比如,可以将需要进行事务管理的代码块独立为方法等等。
声明式事务管理也有两种常用的方式,一种是基于tx和aop名字空间的xml配置文件,另一种就是基于@Transactional注解。显然基于注解的方式更简单易用,更清爽。
https://www.cnblogs.com/nnngu/p/8627662.html
Spring有七大功能模块,分别是Spring Core,AOP,ORM,DAO,MVC,WEB,Context。 1,Spring Core Core模块是Spring的核心类库,Spring的所有功能都依赖于该类库,Core主要实现IOC功能,Sprign的所有功能都是借助IOC实现的。
ORM的全称是Object Relational Mapping,即对象关系映射。它的实现思想就是将关系数据库中表的数据映射成为对象,以对象的形式展现,这样开发人员就可以把对数据库的操作转化为对这些对象的操作。因此它的目的是为了方便开发人员以面向对象的思想来实现对数据库的操作。
3.Spring DAO: DAO (Data Access Object)提供了JDBC的抽象层,它可消除冗长的JDBC编码和解析数据库厂商特有的错误代码。 并且,JDBC封装包还提供了一种比编程性更好的声明性事务管理方法,不仅仅是实现了特定接口,而且对所有的POJOs(plain old Java objects)都适用。
对于ORM Spring没有提供自己的实现。只对JDBC和其他ORM框架进行了封装。
1.Serial收集器
单线程收集器,收集时会暂停所有工作线程(我们将这件事情称之为Stop The World,下称STW),使用复制收集算法,虚拟机运行在Client模式时的默认新生代收集器。
2.ParNew收集器
ParNew 收集器就是Serial的多线程版本,除了使用多条收集线程外,其余行为包括算法、STW、对象分配规则、回收策略等都与Serial收集器一摸一样。对 应的这种收集器是虚拟机运行在Server模式的默认新生代收集器,在单CPU的环境中,ParNew收集器并不会比Serial收集器有更好的效果。
3.Parallel Scavenge收集器
Parallel Scavenge收集器(下称PS收集器)也是一个多线程收集器,也是使用复制算法,但它的对象分配规则与回收策略都与ParNew收集器有所不同,它是 以吞吐量最大化(即GC时间占总运行时间最小)为目标的收集器实现,它允许较长时间的STW换取总吞吐量最大化。
4.Serial Old收集器
Serial Old是单线程收集器,使用标记-整理算法,是老年代的收集器,上面三种都是使用在新生代收集器。
5.Parallel Old收集器
老年代版本吞吐量优先收集器,使用多线程和标记-整理算法,JVM 1.6提供,在此之前,新生代使用了PS收集器的话,老年代除Serial Old外别无选择,因为PS无法与CMS收集器配合工作。
6.CMS(Concurrent Mark Sweep)收集器
CMS 是一种以最短停顿时间为目标的收集器,使用CMS并不能达到GC效率最高(总体GC时间最小),但它能尽可能降低GC时服务的停顿时间,这一点对于实时或 者高交互性应用(譬如证券交易)来说至关重要,这类应用对于长时间STW一般是不可容忍的。CMS收集器使用的是标记-清除算法,也就是说它在运行期间会 产生空间碎片,所以虚拟机提供了参数开启CMS收集结束后再进行一次内存压缩。
效率:System.arraycopy > clone > Arrays.copyOf > for循环
(1)从速度上看:System.arraycopy > clone > Arrays.copyOf > for
(2)for的速度之所以最慢是因为下标表示法每次都从起点开始寻位到指定下标处(现代编译器应该对其有进行优化,改为指针),另外就是它每一次循环都要判断一次是否达到数组最大长度和进行一次额外的记录下标值的加法运算。
(3)查看Arrays.copyOf的源码可以发现,它其实本质上是调用了System.arraycopy。之所以时间差距比较大,是因为很大一部分开销全花在了Math.min函数上了。
这里面在System类源码中给出了arraycopy的方法,是native方法,也就是本地方法,肯定是最快的
解析:处理异常常用的两种方式:
1、try...catch(捕获处理机制);
2、throws(冒泡处理机制).
注意细节:使用try...catch块捕获时可以没有catch块,但当没用catch块的时候必须得有finally块.故选A)
在GoF设计模式中,结构型模式有:
外观模式为子系统中的一组接口提供了同意的界面,外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。
外观模式中,客户对各个具体的子系统是不了解的,所以对这些子系统进行了封装,对外只提供了用户所明白的单一而简单的接口,用户直接使用这个接口就可以完成操作,而不用去理睬具体的过程,而且子系统的变化不会影响到用户,这样就做到了信息隐蔽。
享元模式为运用共享技术有效的支持大量细粒度的对象。因为它可以通过共享大幅度地减少单个实例的数目,避免了大量非常相似类的开销。.
享元模式是一个类别的多个对象共享这个类别的一个对象,而不是各自再实例化各自的对象。这样就达到了节省内存的目的。
i++ 使用i的值之后 i的值 +1
++i 在使用i 之前先使 i 的值加 1
i-- 使用 i 的值之后使 i 的值 -1
--i 使用 i 之前 先使 i 的值 -1
1、一个类可以有多个接口; 2、一个类只能继承一个父类; 3、接口中可以不声明任何方法,和成员变量 interface testinterface{ } 4、抽象类可以不包含抽象方法,但有抽象方法的类一定要声明为抽象类 abstract class abstclass{ abstract void meth(); }
元字符
|
描述
|
\
|
将下一个字符标记符、或一个向后引用、或一个八进制转义符。例如,“\\n”匹配\n。“\n”匹配换行符。序列“\\”匹配“\”而“\(”则匹配“(”。即相当于多种编程语言中都有的“转义字符”的概念。
|
^
|
匹配输入字符串的开始位置。如果设置了RegExp对象的Multiline属性,^也匹配“\n”或“\r”之后的位置。
|
$
|
匹配输入字符串的结束位置。如果设置了RegExp对象的Multiline属性,$也匹配“\n”或“\r”之前的位置。
|
*
|
匹配前面的子表达式任意次。例如,zo*能匹配“z”,也能匹配“zo”以及“zoo”。*等价于o{0,}
|
+
|
匹配前面的子表达式一次或多次(大于等于1次)。例如,“zo+”能匹配“zo”以及“zoo”,但不能匹配“z”。+等价于{1,}。
|
?
|
匹配前面的子表达式零次或一次。例如,“do(es)?”可以匹配“do”或“does”中的“do”。?等价于{0,1}。
|
{n}
|
n是一个非负整数。匹配确定的n次。例如,“o{2}”不能匹配“Bob”中的“o”,但是能匹配“food”中的两个o。
|
{n,}
|
n是一个非负整数。至少匹配n次。例如,“o{2,}”不能匹配“Bob”中的“o”,但能匹配“foooood”中的所有o。“o{1,}”等价于“o+”。“o{0,}”则等价于“o*”。
|
{n,m}
|
m和n均为非负整数,其中n<=m。最少匹配n次且最多匹配m次。例如,“o{1,3}”将匹配“fooooood”中的前三个o为一组,后三个o为一组。“o{0,1}”等价于“o?”。请注意在逗号和两个数之间不能有空格。
|
?
|
当该字符紧跟在任何一个其他限制符(*,+,?,{n},{n,},{n,m})后面时,匹配模式是非贪婪的。非贪婪模式尽可能少的匹配所搜索的字符串,而默认的贪婪模式则尽可能多的匹配所搜索的字符串。例如,对于字符串“oooo”,“o+”将尽可能多的匹配“o”,得到结果[“oooo”],而“o+?”将尽可能少的匹配“o”,得到结果 ['o', 'o', 'o', 'o']
|
.点
|
匹配除“\r\n”之外的任何单个字符。要匹配包括“\r\n”在内的任何字符,请使用像“[\s\S]”的模式。
|
(pattern)
|
匹配pattern并获取这一匹配。所获取的匹配可以从产生的Matches集合得到,在VBScript中使用SubMatches集合,在JScript中则使用$0…$9属性。要匹配圆括号字符,请使用“\(”或“\)”。
|
(?:pattern)
|
非获取匹配,匹配pattern但不获取匹配结果,不进行存储供以后使用。这在使用或字符“(|)”来组合一个模式的各个部分时很有用。例如“industr(?:y|ies)”就是一个比“industry|industries”更简略的表达式。
|
(?=pattern)
|
非获取匹配,正向肯定预查,在任何匹配pattern的字符串开始处匹配查找字符串,该匹配不需要获取供以后使用。例如,“Windows(?=95|98|NT|2000)”能匹配“Windows2000”中的“Windows”,但不能匹配“Windows3.1”中的“Windows”。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始。
|
(?!pattern)
|
非获取匹配,正向否定预查,在任何不匹配pattern的字符串开始处匹配查找字符串,该匹配不需要获取供以后使用。例如“Windows(?!95|98|NT|2000)”能匹配“Windows3.1”中的“Windows”,但不能匹配“Windows2000”中的“Windows”。
|
(?<=pattern)
|
非获取匹配,反向肯定预查,与正向肯定预查类似,只是方向相反。例如,“(?<=95|98|NT|2000)Windows”能匹配“2000Windows”中的“Windows”,但不能匹配“3.1Windows”中的“Windows”。
|
(?<!pattern)
|
非获取匹配,反向否定预查,与正向否定预查类似,只是方向相反。例如“(?<!95|98|NT|2000)Windows”能匹配“3.1Windows”中的“Windows”,但不能匹配“2000Windows”中的“Windows”。这个地方不正确,有问题
此处用或任意一项都不能超过2位,如“(?<!95|98|NT|20)Windows正确,“(?<!95|980|NT|20)Windows 报错,若是单独使用则无限制,如(?<!2000)Windows 正确匹配
|
x|y
|
匹配x或y。例如,“z|food”能匹配“z”或“food”(此处请谨慎)。“[zf]ood”则匹配“zood”或“food”。
|
[xyz]
|
字符集合。匹配所包含的任意一个字符。例如,“[abc]”可以匹配“plain”中的“a”。
|
[^xyz]
|
负值字符集合。匹配未包含的任意字符。例如,“[^abc]”可以匹配“plain”中的“plin”。
|
[a-z]
|
字符范围。匹配指定范围内的任意字符。例如,“[a-z]”可以匹配“a”到“z”范围内的任意小写字母字符。
注意:只有连字符在字符组内部时,并且出现在两个字符之间时,才能表示字符的范围; 如果出字符组的开头,则只能表示连字符本身.
|
[^a-z]
|
负值字符范围。匹配任何不在指定范围内的任意字符。例如,“[^a-z]”可以匹配任何不在“a”到“z”范围内的任意字符。
|
\b
|
匹配一个单词边界,也就是指单词和空格间的位置(即正则表达式的“匹配”有两种概念,一种是匹配字符,一种是匹配位置,这里的\b就是匹配位置的)。例如,“er\b”可以匹配“never”中的“er”,但不能匹配“verb”中的“er”。
|
\B
|
匹配非单词边界。“er\B”能匹配“verb”中的“er”,但不能匹配“never”中的“er”。
|
\cx
|
匹配由x指明的控制字符。例如,\cM匹配一个Control-M或回车符。x的值必须为A-Z或a-z之一。否则,将c视为一个原义的“c”字符。
|
\d
|
匹配一个数字字符。等价于[0-9]。grep 要加上-P,perl正则支持
|
\D
|
匹配一个非数字字符。等价于[^0-9]。grep要加上-P,perl正则支持
|
\f
|
匹配一个换页符。等价于\x0c和\cL。
|
\n
|
匹配一个换行符。等价于\x0a和\cJ。
|
\r
|
匹配一个回车符。等价于\x0d和\cM。
|
\s
|
匹配任何不可见字符,包括空格、制表符、换页符等等。等价于[ \f\n\r\t\v]。
|
\S
|
匹配任何可见字符。等价于[^ \f\n\r\t\v]。
|
\t
|
匹配一个制表符。等价于\x09和\cI。
|
\v
|
匹配一个垂直制表符。等价于\x0b和\cK。
|
\w
|
匹配包括下划线的任何单词字符。类似但不等价于“[A-Za-z0-9_]”,这里的"单词"字符使用Unicode字符集。
|
\W
|
匹配任何非单词字符。等价于“[^A-Za-z0-9_]”。
|
C。由于replaceAll方法的第一个参数是一个正则表达式,而"."在正则表达式中表示任何字符,所以会把前面字符串的所有字符都替换成"/"。
如果想替换的只是".",那么久要写成"\\.".
3.System.setProperty("jdbc.drivers", "com.mysql.jdbc.Driver");
创建一个以JDBC连接数据库的程序,包含7个步骤: 1、加载JDBC驱动程序: 在连接数据库之前,首先要加载想要连接的数据库的驱动到JVM(Java虚拟机), 这通过java.lang.Class类的静态方法forName(String className)实现。 例如: try{ //加载MySql的驱动类 Class.forName("com.mysql.jdbc.Driver"); } catch(ClassNotFoundException e) { System.out.println("找不到驱动程序类 ,加载驱动失败!"); e.printStackTrace(); } 成功加载后,会将Driver类的实例注册到DriverManager类中。 2、提供JDBC连接的URL <blockquote style="vertical-align: baseline;"> <ul style="vertical-align: baseline;"> <li style="vertical-align: baseline;"> 连接URL定义了连接数据库时的协议、子协议、数据源标识。 </li><li style="vertical-align: baseline;"> 书写形式:协议:子协议:数据源标识 </li><li style="vertical-align: baseline;"> 协议:在JDBC中总是以jdbc开始 </li><li style="vertical-align: baseline;"> 子协议:是桥连接的驱动程序或是数据库管理系统名称。 </li><li style="vertical-align: baseline;"> 数据源标识:标记找到数据库来源的地址与连接端口。 jdbc:mysql: //localhost:3306/test?useUnicode=true&characterEncoding=gbk; useUnicode=true:表示使用Unicode字符集。 如果characterEncoding设置为gb2312或GBK,本参数必须设置为true &characterEncoding=gbk;字符编码方式。 3、创建数据库的连接 <blockquote style="vertical-align: baseline;"> <ul style="vertical-align: baseline;"> <li style="vertical-align: baseline;"> 要连接数据库,需要向java.sql.DriverManager请求并获得Connection对象,该对象就代表一个数据库的连接。 </li><li style="vertical-align: baseline;"> 使用DriverManager的getConnectin(String url , String username , String password )方法传入指定的欲连接的数据库的路径、数据库的用户名和密码来获得。 例如: //连接MySql数据库,用户名和密码都是root String url = "jdbc:mysql://localhost:3306/test" ; String username = "root" ; String password = "root" ; try{ Connection con = DriverManager.getConnection(url , username , password ) ; }catch(SQLException se){ System.out.println("数据库连接失败!"); se.printStackTrace() ; } 4、创建一个Statement <blockquote style="vertical-align: baseline;"> <ul style="vertical-align: baseline;"> <li style="vertical-align: baseline;"> 要执行SQL语句,必须获得java.sql.Statement实例,Statement实例分为以下3 种类型: <ol style="vertical-align: baseline;"> <li style="vertical-align: baseline;"> 执行静态SQL语句。通常通过Statement实例实现。 </li><li style="vertical-align: baseline;"> 执行动态SQL语句。通常通过PreparedStatement实例实现。 </li><li style="vertical-align: baseline;"> 执行数据库存储过程。通常通过CallableStatement实例实现。 具体的实现方式: Statement stmt = con.createStatement() ; PreparedStatement pstmt = con.prepareStatement(sql) ; CallableStatement cstmt = con.prepareCall("{CALL demoSp(? , ?)}") ; 5、执行SQL语句 <blockquote style="vertical-align: baseline;"> <ul style="vertical-align: baseline;"> <li style="vertical-align: baseline;"> Statement接口提供了三种执行SQL语句的方法:executeQuery 、executeUpdate和execute <ol style="vertical-align: baseline;"> <li style="vertical-align: baseline;"> ResultSet executeQuery(String sqlString):执行查询数据库的SQL语句,返回一个结果集(ResultSet)对象。 </li><li style="vertical-align: baseline;"> int executeUpdate(String sqlString):用于执行INSERT、UPDATE或 DELETE语句以及SQL DDL语句,如:CREATE TABLE和DROP TABLE等 </li><li style="vertical-align: baseline;"> execute(sqlString):用于执行返回多个结果集、多个更新计数或二者组合的 语句。 ResultSet rs = stmt.executeQuery("SELECT * FROM ...") ; int rows = stmt.executeUpdate("INSERT INTO ...") ; boolean flag = stmt.execute(String sql) ; <ul style="vertical-align: baseline;text-align: right;"> <li style="vertical-align: baseline;"> 1 </li><li style="vertical-align: baseline;"> 2 </li><li style="vertical-align: baseline;"> 3 6、处理结果 <blockquote style="vertical-align: baseline;"> <ul style="vertical-align: baseline;"> <li style="vertical-align: baseline;"> 两种情况: <ol style="vertical-align: baseline;"> <li style="vertical-align: baseline;"> 执行更新返回的是本次操作影响到的记录数。 </li><li style="vertical-align: baseline;"> 执行查询返回的结果是一个ResultSet对象。 <ul style="vertical-align: baseline;color: rgb(153,153,153);"> <li style="vertical-align: baseline;"> ResultSet包含符合SQL语句中条件的所有行,并且它通过一套get方法提供了对这些 行中数据的访问。 </li><li style="vertical-align: baseline;"> 使用结果集(ResultSet)对象的访问方法获取数据: while(rs.next()){ String name = rs.getString("name") ; String pass = rs.getString(1) ; // 此方法比较高效 } <ul style="vertical-align: baseline;text-align: right;"> <li style="vertical-align: baseline;"> 1 </li><li style="vertical-align: baseline;"> 2 </li><li style="vertical-align: baseline;"> 3 </li><li style="vertical-align: baseline;"> 4 (列是从左到右编号的,并且从列1开始) 7、关闭JDBC对象 操作完成以后要把所有使用的JDBC对象全都关闭,以释放JDBC资源,关闭顺序和声 明顺序相反: 1、关闭记录集 2、关闭声明 if(rs != null){ // 关闭记录集 try{ rs.close() ; }catch(SQLException e){ e.printStackTrace() ; } } if(stmt != null){ // 关闭声明 try{ stmt.close() ; }catch(SQLException e){ e.printStackTrace() ; } } if(conn != null){ // 关闭连接对象 try{ conn.close() ; }catch(SQLException e){ e.printStackTrace() ; } }
Java的静态方法属于类的成员,实例方法属于对象的成员。
===========================
javaScript 的常用事件
onblur 当元素失去焦点触发此事件
onchange 当前元素失去焦点并且元素内容发生改变时触发此事件
onfocus 当某个元素获得焦点时触发此事件
onsubmit 当表单被提交时触发此事件
onload 当页面加载完成触发此事件。、
http是一种超文本传输协议 是一种 请求/响应式协议 客户端在与服务器端建立连接后就可以向服务器端发送请求,这种请求比成为http请求
http 是无状态协议,无状态是指协议对于事务处理没有记忆能力,如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。
==============================================
请求参数中的中文乱码
对于post 请求只需要一步
request.setCharacterEncoding("UTF_8")
对于get 请求 也需要
new String(name.getBytes("iso8859-1","UTF_8"))
如果浏览器请求另外一个web资源的时候,用于响应封装消息体的HttpServletResponse 对象已经创建,
该对象在编码时采用默认的ISO-8859-1
当客户端对接收到的数据进行解码时,WEB服务器会继续保持调用HttpServletResponse
对象中的信息,所以会对输出的东西产生乱码
解决办法: response.setContentType("text/html","charset=utf-8");
===========================
cookie 的作用类似会员卡
当用户通过浏览器发消息给服务器时服务器会给浏览器响应一些信息,这些信息都保存在Cookie 中这样当浏览器再次访问服务器时
都会在请求头中将Cookie发送给服务器方便服务器对浏览器做出正确的响应。
服务器向客户端发送Cookie时,会在Htttp 响应头字段中增加Set-Cookie 响应头字段
set-cookie 头字段中设置的Cookie遵循一定的语法格式
Set-Cookie:user=itcast; Path=/
上述用例中;User表示Cookie的名称 itcast 表示Cookie的值 Path表示Cookie的属性,Cookie必须以键值对的形式存在,其属性可以有多个,但是这些
属性之间务必使用 ; 或者 空格 分开。
Cookie 保存在浏览器的缓冲区中,Cookie一旦创建它的名称就不能修改,Cookie值可以为任何值,创建后允许被修改
Cookie 技术可以将用户信息保存在各自的浏览器中,并且可以在多次请求下实现数据的共享,但是如果传递的消息比较多使用Cookie
显然会增大服务器端处理的难度,这时可以使用session技术,Session是一种将会话数据保存在服务器端的技术
=============================
jsp容器仙剑jsp文件转换成一个java 源文件在转换过程中如果发现,jsp文件中存在任何语法错误,则中断转换过程,并向服务器端和客户端返回错误信息
,如果转换成功,则jsp容器将会生成java的源文件然后编译成字节码文件 .class 改class 文件就是一个Servlet Servlet容器hi像处理其他Servlet一样处理它
由Servlet容器加载转换后的Servlet类(.class) 创建一个Servlet实例并执行Servlet的jspInit()方法 ,并且这个方法在Servlet整个生命周期中只会执行一次
执行jspService()方法来处理客户端的请求,对于每一个请求jsp容器就会创建一个新的线程来处理它,如果多个客户端同时请求该jsp文件则jsp容器也会创建多个线程
使得每一个客户端请求都对应一个线程,Servlet实例是常驻内存的所以响应速度非常快,如果jsp页面辈成新编译了会使用重新编译后的结果取代内存中常驻的Servlet并继续处理过程
=========================================
jsp的隐式对象(内置对象)
out : 用于页面输出
request :得到请求用户信息
response:服务器象客户端的回应信息
config: 服务器配置,可以取得初始化参数
session:用来保存用户的信息
application:所有用户的共享信息
page: 指当前页面转换后的Servlet类的实例
pageContext: Jsp页面容器
exception: 表示jsp页面所发生的异常,在错误页面中才起作用
在jsp页面中 pageContext对象可以获取jsp的其他8个隐式对象
===============================
为了降低jsp页面的复杂度,增强代码的重用性Sun公司制定了一套标准标签库JSTL
同时为了获取Servlet域对象中存储的数据
EL的隐式对象
EL中的隐式对象共有11 个
pageContext 对用于jsp页面中中的pageContext 对象
pageScope 代表page 域中保存属性的map对象
requestScope 代表request域中保存属性的map对象
sessionScope 代表session域中保存属性的map对象
applicationScope 代表application域中保存属性的map对象
param 表示一个保存了所有请求的Map对象
paramValue 表示一个保存了所有请求的Map对象,他对于某个请求参数返回的是一个String类型的数组
header 表示一个保存了所有HTTP请求头字段的Map对象
headerValues 表示一个保存了所有HTTP请求头字段的Map对象,返回String类型数组
cookie 用来取得使用者的Cookie的值,cookie的类型是map
initParam 表示一个保存了所有WEB应用初始化参数的map 对象。
======================
filter 过滤器拦截的范围 jsp;Servlet Html
================================================
一般关系数据模型和对象数据模型之间有以下对应关系:表对应类,记录对应对象,表的字段对应类的属性
目前ORMapping只是规定了数据结构和数据集的映射关系,还没到规定赖关系的阶段
字符用单引号,字符串用双引号,与引号中的内容无关
t.join(); //使调用线程 t 在此之前执行完毕。
t.join(1000); //等待 t 线程,等待时间是1000毫秒
Java中对字段属性是静态绑定,方法成员是动态绑定,这里错在:在子类中试图访问父类的private字段,所以编译不通过,将private去掉就可访问,不是动态绑定的问题,它本来就属于静态绑定
类加载过程
类从被加载到虚拟机内存中开始,到卸载出内存为止,它的整个生命周期包括:加载(Loading)、验证(Verification)、准备(Preparation)、解析(Resolution)、初始化(Initialization)、使用(Using)和卸载(Unloading)7个阶段。其中准备、验证、解析3个部分统称为连接(Linking)。如图所示。
加载、验证、准备、初始化和卸载这5个阶段的顺序是确定的,类的加载过程必须按照这种顺序按部就班地开始,而解析阶段则不一定:它在某些情况下可以在初始化阶段之后再开始,这是为了支持Java语言的运行时绑定(也称为动态绑定或晚期绑定)。以下陈述的内容都已HotSpot为基准。
加载
在加载阶段(可以参考java.lang.ClassLoader的loadClass()方法),虚拟机需要完成以下3件事情:
- 通过一个类的全限定名来获取定义此类的二进制字节流(并没有指明要从一个Class文件中获取,可以从其他渠道,譬如:网络、动态生成、数据库等);
- 将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构;
- 在内存中生成一个代表这个类的java.lang.Class对象,作为方法区这个类的各种数据的访问入口;
加载阶段和连接阶段(Linking)的部分内容(如一部分字节码文件格式验证动作)是交叉进行的,加载阶段尚未完成,连接阶段可能已经开始,但这些夹在加载阶段之中进行的动作,仍然属于连接阶段的内容,这两个阶段的开始时间仍然保持着固定的先后顺序。
验证
验证是连接阶段的第一步,这一阶段的目的是为了确保Class文件的字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟机自身的安全。
验证阶段大致会完成4个阶段的检验动作:
- 文件格式验证:验证字节流是否符合Class文件格式的规范;例如:是否以魔术0xCAFEBABE开头、主次版本号是否在当前虚拟机的处理范围之内、常量池中的常量是否有不被支持的类型。
- 元数据验证:对字节码描述的信息进行语义分析(注意:对比javac编译阶段的语义分析),以保证其描述的信息符合Java语言规范的要求;例如:这个类是否有父类,除了java.lang.Object之外。
- 字节码验证:通过数据流和控制流分析,确定程序语义是合法的、符合逻辑的。
- 符号引用验证:确保解析动作能正确执行。
验证阶段是非常重要的,但不是必须的,它对程序运行期没有影响,如果所引用的类经过反复验证,那么可以考虑采用-Xverifynone参数来关闭大部分的类验证措施,以缩短虚拟机类加载的时间。
准备
准备阶段是正式为类变量分配内存并设置类变量初始值的阶段,这些变量所使用的内存都将在方法区中进行分配。这时候进行内存分配的仅包括类变量(被static修饰的变量),而不包括实例变量,实例变量将会在对象实例化时随着对象一起分配在堆中。其次,这里所说的初始值“通常情况”下是数据类型的零值,假设一个类变量的定义为:
1
|
publicstaticintvalue=123;
|
那变量value在准备阶段过后的初始值为0而不是123.因为这时候尚未开始执行任何java方法,而把value赋值为123的putstatic指令是程序被编译后,存放于类构造器()方法之中,所以把value赋值为123的动作将在初始化阶段才会执行。
至于“特殊情况”是指:public static final int value=123,即当类字段的字段属性是ConstantValue时,会在准备阶段初始化为指定的值,所以标注为final之后,value的值在准备阶段初始化为123而非0.
解析
解析阶段是虚拟机将常量池内的符号引用替换为直接引用的过程。解析动作主要针对类或接口、字段、类方法、接口方法、方法类型、方法句柄和调用点限定符7类符号引用进行。
初始化
类初始化阶段是类加载过程的最后一步,到了初始化阶段,才真正开始执行类中定义的java程序代码。在准备极端,变量已经付过一次系统要求的初始值,而在初始化阶段,则根据程序猿通过程序制定的主管计划去初始化类变量和其他资源,或者说:初始化阶段是执行类构造器<clinit>()方法的过程.
子类的构造方法总是先调用父类的构造方法,如果子类的构造方法没有明显地指明使用父类的哪个构造方法,子类就调用父类不带参数的构造方法。
而父类没有无参的构造函数,所以子类需要在自己的构造函数中显示的调用父类的构造函数。
在子类继承父类中,一般有一行super的语句,需要记住三种使用方法:
1、super.变量/对象名;
使用这种方法可以直接访问父类中的变量或对象,进行修改赋值等操作
2、super.方法名();
直接访问并调用父类中的方法
3、super();
调用父类的初始化方法,其实就是调用父类中的public xxx()方法,通常第三种指代的是super()的省略写法,系统会默认添加此句。
特殊情况:如果父类没有无参的构造函数,所以子类需要在自己的构造函数中显示的调用父类的构造函数,即不能使用系统默认的“super()”,而需要显性写出super(xxx)
Jsp只会在客户端第一次发请求的时候被编译,之后的请求不会再编译,同时tomcat能自动检测jsp变更与否,变更则再进行编译。
第一次编译并初始化时调用: init() ;销毁调用: destroy() 。在整个jsp生命周期中均只调用一次。
service()方法是接收请求,返回响应的方法。每次请求都执行一次,该方法被HttpServlet封装为doGet和doPost方法
Java程序的种类有:
(a)内嵌于Web文件中,由浏览器来观看的_Applet
(b)可独立运行的 Application
(c)服务器端的 Servlets
―Java小程序”不能独立运行(嵌入到Web页中)。
由Java兼容浏览器控制执行。
public class Enclosingone { //非静态内部类 public class InsideOne {} //静态内部类 public static class InsideTwo{} } class Mytest02{ public static void main(String args []){ Enclosingone.InsideOne obj1 = new Enclosingone(). new InsideOne(); //非静态内部类对象 Enclosingone.InsideTwo obj2 = new Enclosingone.InsideTwo(); //静态内部类对象 } } |
封装就是将属性私有化,提供公有的方法访问私有属性。------------------- 所以CD错误。
做法就是:修改属性的可见性来限制对属性的访问,并为每个属性创建一对取值( getter )方法和赋值( setter )方法,用于对这些属性的访问。
如: private String name;
public String getName(){
return;
}
public void setName(String name){
this.name=name;
}
2、 为什么需要封装?
通过封装,可以实现对属性的数据访问限制,同时增加了程序的可维护性。
class A{ public A foo(){return this;} } class B extends A{ public A foo(){ return this; } } class C extends B { _______ }
如果子类的方法名与父类的方法名和参数相同,jvm会认为子类是想要覆盖(重写)父类的方法的,如果是重写,那么不仅方法名要相同,返回值和参数列表都要相同,为什么要这样设定?
我想应该是为了约束吧。如果方法名相同,参数相同但返回值不同,会有可能导致jvm认为这两个方法不是被子类方法重写了(继承中不存在重载),那么子类通过这个方法名调用方法的时候,就会有有歧义了,不能确定是调用自身的方法还是父类的方法。比如说B选项这种情况,public int foo(){return 1;},当我c.foo();那c此时调用的是自身foo方法还是父类的呢?所以jvm如果发现是方法名和参数一样的方法,默认为这是重写父类方法。
Ant和Maven都是基于Java的构建(build)工具。理论上来说,有些类似于(Unix)C中的make ,但没有make的缺陷。Ant是软件构建工具,Maven的定位是软件项目管理和理解工具。
Ant特点
没有一个约定的目录结构 必须明确让ant做什么,什么时候做,然后编译,打包 没有生命周期,必须定义目标及其实现的任务序列 没有集成依赖管理
Maven特点
拥有约定,知道你的代码在哪里,放到哪里去 拥有一个生命周期,例如执行 mvn install 就可以自动执行编译,测试,打包等构建过程 只需要定义一个pom.xml,然后把源码放到默认的目录,Maven帮你处理其他事情 拥有依赖管理,仓库管理
重载是在同一个类中,有多个方法名相同,参数列表不同(参数个数不同,参数类型不同),与方法的返回值无关,与权限修饰符无关,B中的参数列表和题目的方法完全一样了。
必须明确行数,列数不重要
数组有length属性,字符串只有length()方法
内存泄露(Memory Leak)是指一个不再被使用的对象或者变量还在内存中占有存储空间。
在C/C++语言中,内存泄露出现在开发人员忘记释放已分配的内存就会造成内存泄露。在java语言中引入垃圾回收机制,有GC负责进行回收不再使用的对象,释放内存。但是还是会存在内存泄露的问题。
内存泄露主要有两种情况:1.在堆中申请的空间没有释放。2.对象已不再被使用(注意:这里的不在被使用是指对程序来说没有用处,如数据库连接使用后没有关。但是还是存在着引用),但是仍然在内存中保留着。GC机制的引入只能解决第一种情况,对于第2种情况无法保证不再使用的对象会被释放。java语言中的内存泄露主要指第2种情况。 内存泄露的原因:1.静态集合类。如HashMap和Vector。这些容器是静态的,生命周期和程序的生命周期一致,那么在容器中对象的生命周期也和其一样,对象在程序结束之前将不能被释放,从而会造成内存泄露。2.各种连接,如数据库连接,网络连接,IO连接,不再使用时如果连接不释放容易造成内存泄露。3.监听器,释放对象时往往没有相应的删除监听器,可能会导致内存泄露。 内存溢出(OOM)是指程序在申请内存时没有足够的内存供使用,进而导致程序崩溃这是结果描述。内存泄露(Memory Leak)最终会导致内存溢出。
同一个类内,private变量可以访问,所以CD错。由于x是static的,存贮在类内,而不是对象内,所以++、--操作的是同一个变量。
ArrayList的构造函数总共有三个:
类的初始化过程也就是方法执行的过程 父类的静态变量-父类的静态代码块 子类的静态变量-子类的静态代码块 父类的非静态变量-父类的非静态代码块-父类的构造函数 子类的非静态变量-子类的非静态代码块-子类的构造函数 规律就是 父类先于子类 静态的先于非静态的 变量先于代码块
派生类本身的构造函数 这个应该指的是构造代码块
枚举类有三个实例,故调用三次构造方法,打印三次It is a account type
JEE5.0中的Servlet相关的就下面这几个包: javax.servlet javax.servlet.jsp java.servlet.jsp.el java.servlet.jsp.tagext 而最用得多的就是 javax.servlet javax.servlet.http 这两个包了.
构造函数的作用是完成对象的初始化。当程序执行到new操作符时, 首先去看new操作符后面的类型,因为知道了类型,才能知道要分配多大的内存空间。分配完内存之后,再调用构造函数,填充对象的各个域,这一步叫做对象的初始化。而选项B、D中,对象的初始化并不是通过构造函数完成的,而是读取别的内存区域中的对象的各个域来完成。
A. request.getAttribute:getAttribute是在服务器端的操作。
比如说 request.setAttribute(k,v),其行为动作在服务器端。
而在服务端放入cookies是通过response.addCookie(cookie)。因此,A错了
B. Accept 浏览器可接受的MIME类型
Accept-Charset 浏览器支持的字符编码
Accept-Encoding 浏览器知道如何解码的数据编码类型(如 gzip)。Servlets 可以预先检查浏览器是否支持gzip并可以对支持gzip的浏览器返回gzipped的HTML页面,并设置Content-Encoding回应头(response header)来指出发送的内容是已经gzipped的。在大多数情况下,这样做可以加快网页下载的速度。
Accept-Language 浏览器指定的语言,当Server支持多语种时起作用。
Authorization 认证信息,一般是对服务器发出的WWW-Authenticate头的回应。
Connection 是否使用持续连接。如果servlet发现这个字段的值是Keep-Alive,或者由发出请求的命令行发现浏览器支持 HTTP 1.1 (持续连接是它的默认选项),使用持续连接可以使保护很多小文件的页面的下载时间减少。
Content-Length (使用POST方法提交时,传递数据的字节数)
Cookie (很重要的一个Header,用来进行和Cookie有关的操作,详细的信息将在后面的教程中介绍)
Host (主机和端口)
If-Modified-Since (只返回比指定日期新的文档,如果没有,将会反回304 "Not Modified")
Referer (URL)
User-Agent (客户端的类型,一般用来区分不同的浏览器)
C.request.getParameter()方法获取从客户端中通过get 或者post方式传送到服务器端的参数。行为操作在服务器端。所以cookies明显不是通过url或者form表单提交过来的。C错
D.看方法名字就行了。
java是不需要使用者关注内存分配以及管理的
MVC只是将分管不同功能的逻辑代码进行了隔离,增强了可维护和可扩展性,增强代码复用性,因此可以减少代码重复。但是不保证减少代码量,多层次的调用模式还有可能增加代码量
当你创建一个新的实例对象时,它会得到一块新的内存空间。但是类中的静态成员变量是所有对象共有的,也就是在一片属于类的存储空间中,被所有对象共有。
A:不存在x[25] 索引从0开始到length-1
B:x[24] 存的是默认值0(java中没有'\0'这一说)
C:超出内存 正确
D:第二元素
玩文字游戏呢!指向的内容在常量池中不可以变,但是可以改变string的指向
第四行:因为有new关键字,所以在heap中开辟了一块新内存放置值为59的Integer对象。
sleep和wait的区别有: 1,这两个方法来自不同的类分别是Thread和Object 2,最主要是sleep方法没有释放锁,而wait方法释放了锁,使得敏感词线程可以使用同步控制块或者方法。 3,wait,notify和notifyAll只能在同步控制方法或者同步控制块里面使用,而sleep可以在 任何地方使用 synchronized(x){ x.notify() //或者wait() } 4,sleep必须捕获异常,而wait,notify和notifyAll不需要捕获异常
因为两次new() 分出的内存也不同
析构函数(destructor) 与 构造函数 相反,当对象结束其 生命周期时(例如对象所在的函数已调用完毕),系统自动执行析构函数。析构函数往往用来做“清理善后” 的工作(例如在建立对象时用new开辟了一片内存空间,应在退出前在析构函数中用delete释放)。
A:.java编译成的是字节码,再被各系统的jvm翻译成本系统可以识别的机器码,这就是java一次编程多平台应用的跨平台性 B:java源文件生成的是class文件,与系统无关 C:注意字节码和机器码不是一回事 java程序在运行时字节码才会被jvm翻译成机 器码,所以说java是解释性语言 D:注意jvm的版本,好比人穿裤子,一条裤子能被任何人穿上吗
虚拟机中的共划分为三个代:年轻代(Young Generation)、年老点(Old Generation)和持久代(Permanent Generation)。其中持久代主要存放的是Java类的类信息,与垃圾收集要收集的Java对象关系不大。年轻代和年老代的划分是对垃圾收集影响比较大的。
年轻代:
所有新生成的对象首先都是放在年轻代的。年轻代的目标就是尽可能快速的收集掉那些生命周期短的对象。年轻代分三个区。一个Eden区,两个 Survivor区(一般而言)。大部分对象在Eden区中生成。当Eden区满时,还存活的对象将被复制到Survivor区(两个中的一个),当这个 Survivor区满时,此区的存活对象将被复制到另外一个Survivor区,当这个Survivor去也满了的时候,从第一个Survivor区复制过来的并且此时还存活的对象,将被复制“年老区(Tenured)”。需要注意,Survivor的两个区是对称的,没先后关系,所以同一个区中可能同时存在从Eden复制过来对象,和从前一个Survivor复制过来的对象,而复制到年老区的只有从第一个Survivor去过来的对象。而且,Survivor区总有一个是空的。同时,根据程序需要,Survivor区是可以配置为多个的(多于两个),这样可以增加对象在年轻代中的存在时间,减少被放到年老代的可能。
年老代:
在年轻代中经历了N次垃圾回收后仍然存活的对象,就会被放到年老代中。因此,可以认为年老代中存放的都是一些生命周期较长的对象。
suspend() 和 resume() 方法:两个方法配套使用,suspend()使得线程进入阻塞状态,并且不会自动恢复,必须其对应的 resume() 被调用,才能使得线程重新进入可执行状态