Java基础面试

Java基础面试,第1张

Java基础面试 为什么要重写hashcode()方法

主要原因是默认从Object继承来的hashCode是基于对象的ID实现的。
如果你重写了equals,比如说是基于对象的内容实现的,而保留hashCode的实现不变,那么很可能某两个对象明明是“相等”,而hashCode却不一样。
这样,当你用其中的一个作为键保存到hashMap、hasoTable或hashSet中,再以“相等的”找另一个作为键值去查找他们的时候,则根本找不到。

HashMap

底层是数组+链表+红黑树,哈希表

key : value结构,key不可重复,重复则value值被覆盖

HashMap的key会先后调用hashCode and equals方法,两个方法都需要重写

map.put(k,v)、map.get(k)实现原理:

调用k的hashCode()方法,找到数组下标,再与链表上元素进行equals()。

单向链表中元素超过8个,那么单向链表这种数据结构会变成红黑树数据结构。

当红黑树上的节点数量小于6个,会重新把红黑树变成单向链表数据结构。

hashmap集合的默认初始化容量为16,默认加载因子为0.75,当hashMap集合底层数组的容量达到75%时,数组就开始扩容。

默认的equals方法同==

对于值对象,==比较的是两个对象的值对于引用对象,比较的是两个对象的地址 map遍历

keySet().iterator();

entrySet().iterator();

substring截取字符串

substring(2); [2,结束]

substring(2,4); [2,4)

为什么左含右不含

String st1 = "abcdefghi";
String st2 = "ss";
st1.substring(0,st2.length());  //返回"ab"
//length值比索引值多1,右不含正好

concat(“拼接字符串”);

contains(“包含字符串”)

JDBC

Class.forName(“com.mysql.jdbc.Driver”):加载注册驱动

DriverManager驱动:获取连接,返回一个连接

Connection对象:连接

Statement对象:执行SQL

ResultSet对象:结果集

事务

DML(Data Manipulation Language)数据 *** 纵语言:对数据进行 *** 作
select、insert、delete、update

DDL(Data Definition Language)数据库定义语言:

改变表(table)结构,对对象进行处理,表、视图、索引、存储组(STOGROUP)
create(创建)、alter(修改)、drop(删除)

DCL(Data Control Language) 数据库控制语言:设置或更改数据库用户或角色权限
grant(授予权限)、deny、revoke

自动提交

数据一旦提交,不可回滚

DML、DDL一旦执行,自动提交
set autocommit = false; //可取消DML *** 作自动提交,对DDL无效
connection.setAutoCommit(false);

默认再关闭连接时,自动提交数据
connection.close();

事物的ACID属性

原子性(Atomicity)一致性(Consistency)隔离性(Isolation)持久性(Durability) 隔离级别

并发问题

脏读:T1读取了T2更新但没有提交的数据

不可重复读:T1读取数据,T2更新数据,T1再读,两次数据不一致

幻读:T1读取数据,T2插入数据,T1再读,数据不一致,多出几行

隔离级别

read uncommitted(读未提交)read committed(读已提交):oracle默认
解决脏读
在一个事务内,其他用户 *** 作数据库且提交了,自己会读到修改后的数据repeatable read(可重复读):mysql默认
解决不可重复读
在一个事务内,其他用户 *** 作数据库不影响 自己读取数据,事务未提交期间数据不会改变serializable(串行化):解决幻读 SQL

更新:修改现有行

UPDATE 表名称 SET 列名称=新值,列名称=新值 WHERe 列名称=某值

update user set name='jack' where id=1;

插入:创建新行

INSERT INTO 表名称 VALUES (值1, 值2,....)
INSERT INTO 表名称 (列1, 列2,...) VALUES (值1, 值2,....)

INSERT INTO user VALUES("jack",12,"男");
INSERT INTO user(name,a) VALUES("jack",12,"男");

删除

DELETE FROM 表名称 WHERe 列名称 = 值
HashMap和Hashtable的区别

HashMap不是线程安全的,HashMap允许null key和null value,而hashtable不允许。效率高一点。

HashTable是线程安全

sleep与wait的区别 1、来自不同的类

sleep来自Thread类,和wait来自Object类。

2、有没有释放锁(释放资源)

sleep是Thread的静态类方法,谁调用的谁去睡觉,即使在a线程里调用了b的sleep方法,实际上还是a去睡觉,要让b线程睡觉要在b的代码中调用sleep。

最主要是sleep方法没有释放锁,而wait方法释放了锁,使得其他线程可以使用同步控制块或者方法。

sleep不出让系统资源;wait是进入线程等待池等待,出让系统资源,其他线程可以占用CPU。一般wait不会加时间限制,因为如果wait线程的运行资源不够,再出来也没用,要等待其他线程调用notify/notifyAll唤醒等待池中的所有线程,才会进入就绪队列等待OS分配系统资源

就是说sleep有时间限制的就像闹钟一样到时候就叫了,而wait是无限期的除非用户主动notify

3、使用范围不同

wait,notify和notifyAll只能在同步控制方法或者同步控制块里面使用,而sleep可以在任何地方使用

4、是否需要捕获异常

sleep必须捕获异常,而wait,notify和notifyAll不需要捕获异常

sleep()方法和yield()方法有什么区别?

①sleep()方法给其他线程运行机会时不考虑线程的优先级,因此会给低优先级的线程以运行的机会;yield()方法只会给相同优先级或更高优先级的线程以运行的机会;

② 线程执行sleep()方法后转入阻塞(blocked)状态,而执行yield()方法后转入就绪(ready)状态;
③ sleep()方法声明抛出InterruptedException,而yield()方法没有声明任何异常;
④ sleep()方法比yield()方法(跟 *** 作系统CPU调度相关)具有更好的可移植性。

join()

在线程B中调用了线程A的Join()方法,直到线程A执行完毕后,才会继续执行线程B。

t.join(); //调用join方法,等待线程t执行完毕
t.join(1000); //等待 t 线程,等待时间是1000毫秒。

final

final修饰属性

基本类型:值不变对象:引用不变

final修饰方法:不可重写

final修饰类:不可继承

final修饰基本类型变量和引用变量

当使用final修饰基本数据类型时,不能对其重新赋值,不能被改变。当使用final修饰引用类型变量时,它仅仅保证他的地址不变,即一直引用同一个对象,但这个对象完全可以发生改变。 static

static修饰方法:

static静态方法来说,是没有this的,因为它不依附于任何对象,既然都没有对象,就谈不上this了。并且由于这个特性,在静态方法中不能访问类的非静态成员变量和非静态成员方法,因为非静态成员方法/变量都是必须依赖具体的对象才能够被调用。

static修饰变量:

静态变量被所有的对象所共享,在内存中只有一个副本,它当且仅当在类初次加载时会被初始化。

static修饰内部类:

1.静态内部类跟静态方法一样,只能访问静态的成员变量和方法,不能访问非静态的方法和属性,但是普通内部类可以访问任意外部类的成员变量和方法
2.静态内部类可以声明普通成员变量和方法,而普通内部类不能声明static成员变量和方法。
3.静态内部类可以单独初始化:
Inner i = new Outer.Inner();
普通内部类初始化:
Outer o = new Outer();
Inner i = o.new Inner();

session和cookie的区别包括:

存储位置不同、安全性不同、存储方向不同、跨域支持不同、依赖条件不同、大小不同。

1、存储位置不同,session 在服务器端,cookie 在客户端(浏览器)

2、安全性不同,cookie存放在客户端,可通过xss漏洞进行攻击,获取用户敏感信息,session 默认被存在在服务器的一个文件里,不容易被获取。

3、存储方向不同,session 可以放在文件、数据库、或内存中都可以。

4、跨域支持不同,cookie支持跨域使用,session只有在同一个站点才能使用。

5、依赖条件不同、session 的运行依赖 session id,而 session id 是存在 cookie 中的,如果浏览器禁用了 cookie ,同时 session 也会失效

6、大小不同,cookie的大小限制为4kB,且一般一个站点只能用20个cookie。

7、session id是维持一个会话的核心就是客户端的唯一标识。

session的创建:

当程序需要为某个客户端的请求创建一个session时,服务器首先检查这个客户端的请求里是否已包含了sessionId,如果已包含则说明以前已经为此客户端创建过session,服务

器就按照sessionId把这个session检索出来使用(检索不到,会新建一个),如果客户端请求不包含sessionId,则为此客户端创建一个session并且生成一个与此session相关

联的sessionId,sessionId的值是一个既不会重复,又不容易被找到规律以仿造的字符串,这个sessionId将被在本次响应中返回给客户端保存。

servlet生命周期

1,创建Servlet对象,调用构造函数,通过服务器反射机制创建Servlet对象,第一次请求时才会创建。(默认)

2,调用Servlet对象的init()方法,初始化Servlet的信息,init()方法只会在创建后被调用一次(初始化阶段)

3,响应请求,调用service()或者是doGet(),doPost()方法来处理请求,这些方法是运行的在多线程状态下的。(响应客户请求阶段)

4, 在长时间没有被调用或者是服务器关闭时,会调用destroy()方法来销毁Servlet对象。(终止阶段)

反射

获取对象三种方式:

1、Class clazz1 = Class.forName(“全限定类名”);

2、Class clazz2 = Person.class;

3、Person p = new Preson(); Class clazz3 = p.getClass();

获取构造器

Construnctor con = clazz1.getConstructor(int.class,String.Class);

通过构造器获取对象

User user = (User)con.newInstance(12,“小明”);

获取成员变量并使用—Filed对象

Class.getField(String) 获取类中可见字段

getDeclaedField(“name”) 获取私有变量 setAccessible(true)

获得方法并使用 Method

Class.getMethod(String, Class…)

Class.getDeclaredMethod(String, Class…)

获得该类的所有接口

Class[] getInterfaces();

SQL

left join(左联接) 返回包括左表中的所有记录和右表中联结字段相等的记录 ,没有显示null
right join(右联接) 返回包括右表中的所有记录和左表中联结字段相等的记录,没有显示null
inner join(等值连接) 只返回两个表中联结字段相等的行

重写与重载之间的区别 区别点重载方法重写方法参数列表必须修改一定不能修改返回类型可以修改一定不能修改异常可以修改可以减少或删除,一定不能抛出新的或者更广的异常访问可以修改一定不能做更严格的限制(可以降低限制)

异常小、访问大

io流

继承关系

InputStream:读取字节流抽象类

FileInputStream:字节输入流FilterInputstream:过滤字节输入流

BufferedInputStream:字节输入缓冲流DataInputStream:数据类型输入处理流 ObjectInputStream:引用类型输入处理流(对象反序列化)ByteArrayInputStream:字节数组输入流

Reader:读取字符流抽象类

InputStreamReader:字符输入处理流,字节流–>字符流

FileReader:字符输入流 BufferedReader:字符输入缓冲流CharArrayReader:字符数组输入流 Array与Arraylist区别

Array:固定长度数组,存储相同类型的基本数据类型或对象

ArrayList:动态数组,可存储不同类型对象,基本数据类型通过自动装拆箱转换为对象

储存的数据类型

ArrayList可以存储不同类型的对象,而Array只能存储相同数据类型的数据。

长度的可变

Array的长度实际上是不可变的,二维变长数组实际上的长度也是固定的,可变的只是其中元素的长度。ArrayList的长度既可以指定(即使指定了长度,也会自动2倍扩容)也可以不指定,是变长的。

存取和增删元素

对于一般的引用类型来说,这部分的影响不是很大,但是对于值类型来说,往ArrayList里面添加和修改元素,都会引起装箱和拆箱的 *** 作,频繁的 *** 作可能会影响一部分效率。

转换

list.toArray()

Arrays.asList()

String、StringBuffer、StringBuilder 创建
String str1 = "hello world";	//字面量创建,添加到常量池
String str1 = new String("hello world"); 
//在类加载的过程中,在运行时常量池中创建了一个"abc"对象,在代码执行过程中创建了一个String对象。
修改
public final class String{ }  //String类被final修饰,不可继承
private final char value[];  //value属性被final修饰,不可更改

对String对象的任何改变都不影响到原对象,相关的任何change *** 作都会生成新的对象。

String string = "";
string += "hello";		//String类执行+= *** 作,底层创建StringBuilder进行添加

JVM自动优化为StringBuilder

StringBuilder str = new StringBuilder(string);
str.append("hello");
str.toString();

StringBuffer、StringBuilder会直接在原对象上添加元素

StringBuffer加锁,比StringBuilder慢

值传递与引用传递

值传递:(形式参数类型是基本数据类型):

方法调用时,实际参数把它的值传递给对应的形式参数,形式参数只是用实际参数的值初始化自己的存储单元内容,是两个不同的存储单元,所以方法执行中形式参数值的改变不影响实际参数的值。

引用传递:(形式参数类型是引用数据类型参数):

也称为传地址。方法调用时,实际参数是对象(或数组),这时实际参数与形式参数指向同一个地址,在方法执行中,对形式参数的 *** 作实际上就是对实际参数的 *** 作,这个结果在方法结束后被保留了下来,所以方法执行中形式参数的改变将会影响实际参数。

数据库范式

1.第一范式(确保每列保持原子性)

2.第二范式(确保表中的每列都和主键相关)

3.第三范式(确保每列都和主键列直接相关,而不是间接相关,消除依赖)

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5703656.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存