面试的java题目

1.哈希表有哪些实现类,哈希表原理是什么?

实现的类:HashMap  HashTable等

HashMap的实现原理:

  1. 利用key的hashCode重新hash计算出当前对象的元素在数组中的下标
  2. 存储时,如果出现hash值相同的key,此时有两种情况。(1)如果key相同,则覆盖原始值;(2)如果key不同(出现冲突),则将当前的key-value放入链表中
  3. 获取时,直接找到hash值对应的下标,在进一步判断key是否相同,从而找到对应值。
  4. 理解了以上过程就不难明白HashMap是如何解决hash冲突的问题,核心就是使用了数组的存储方式,然后将冲突的key的对象放入链表中,一旦发现冲突就在链表中做进一步的对比

 

 

2.String,StringBuffer与StringBuilder的区别

String:String的值是不可变的,这就导致每次对String的操作都会生成新的String对象,不仅效率低下,而且浪费大量优先的内存空间

StringBuffer :StringBuffer是可变类,是线程安全的在多线程操作字符串的类,任何对它指向的字符串的操作都不会产生新的对象。每个 StringBuffer对象都有一定的缓冲区容量,当字符串大小没有超过容量时,不会分配新的容量,当字符串大小超过容量时,会自动增加容量。

StringBuilder:StringBuilder可变类,速度快。线程不安全,在单线程下操作字符串。

 

3.反射原理及应用场景

 

反射机制是一种程序自我分析的能力。用于获取一个类的类变量,构造函数,方法,修饰符。

 

优点:运行期类型的判断,动态类加载,动态代理使用反射。

 

缺点:性能是一个问题,反射相当于一系列解释操作,通知jvm要做的事情,性能比直接的java代码要慢很多。

Class类是反射机制的起源,我们得到Class类对象有三种方法:

1.Class.forName()   2.Object.getClass()  3.类字面常量.class

 

应用场景:

1)Java的反射机制在做基础框架的时候非常有用,有一句话这么说来着:反射机制是很多Java框架的基石。而一般应用层面很少用,不过这种东西,现在很多开源框架基本都已经给你封装好了,自己基本用不着写。典型的除了Hibernate之外,还有Spring也用到很多反射机制。经典的就是在xml文件或者properties里面写好了配置,然后在Java类里面解析xml或properties里面的内容,得到一个字符串,然后用反射机制,根据这个字符串获得某个类的Class实例,这样就可以动态配置一些东西,不用每一次都要在代码里面去new或者做其他的事情,以后要改的话直接改配置文件,代码维护起来就很方便了,同时有时候要适应某些需求,Java类里面不一定能直接调用另外的方法,这时候也可以通过反射机制来实现。
总的来说,自己写的很少,具体什么时候要用那要看需求,反射机制无非就是根据一个String来得到你要的实体对象,然后调用它原来的东西。但是如果是要自己写框架的话,那就会用得比较多了。

2)当你做一个软件可以安装插件的功能,你连插件的类型名称都不知道,你怎么实例化这个对象呢?因为程序是支持插件的(第三方的),在开发的时候并不知道 。所以无法在代码中 New出来 ,但反射可以,通过反射,动态加载程序集,然后读出类,检查标记之后再实例化对象,就可以获得正确的类实例。

3)在编码阶段不知道那个类名,要在运行期从配置文件读取类名, 这时候就没有办法硬编码new ClassName(),而必须用到反射才能创建这个对象.反射的目的就是为了扩展未知的应用。比如你写了一个程序,这个程序定义了一些接口,只要实现了这些接口的dll都可以作为插件来插入到这个程序中。那么怎么实现呢?就可以通过反射来实现。就是把dll加载进内存,然后通过反射的方式来调用dll中的方法。很多工厂模式就是使用的反射。 
(额外提升:https://www.cnblogs.com/AaronCui/p/4911123.html)

 

 

4.线程池的应用

一、线程池使用场景

•单个任务处理时间短

•将需处理的任务数量大

二、使用Java线程池好处

1、使用new Thread()创建线程的弊端:

•每次通过new Thread()创建对象性能不佳。

•线程缺乏统一管理,可能无限制新建线程,相互之间竞争,及可能占用过多系统资源导致死机或oom。

•缺乏更多功能,如定时执行、定期执行、线程中断。

2、使用Java线程池的好处:

•重用存在的线程,减少对象创建、消亡的开销,提升性能。

•可有效控制最大并发线程数,提高系统资源的使用率,同时避免过多资源竞争,避免堵塞。

•提供定时执行、定期执行、单线程、并发数控制等功能。

 

三 Java通过Executors提供四种线程池,分别为:

newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行。
newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。

 

 

5.SQL优化有哪些

1、避免在where子句中使用 is null 或 is not null 对字段进行判断。

select id from table where name is null


在这个查询中,就算我们为 name 字段设置了索引,查询分析器也不会使用,因此查询效率底下。为了避免这样的查询,在数据库设计的时候,尽量将可能会出现 null 值的字段设置默认值,这里如果我们将 name 字段的默认值设置为0,那么我们就可以这样查询:

select id from table where name = 0


2、避免在 where 子句中使用 != 或 <> 操作符。

select name from table where id <> 0

数据库在查询时,对 != 或 <> 操作符不会使用索引,而对于 < 、 <= 、 = 、 > 、 >= 、 BETWEEN AND,数据库才会使用索引。因此对于上面的查询,正确写法应该是:

select name from table where id < 0
union all
select name from table where id > 0
这里我们为什么没有使用 or 来链接 where 后的两个条件呢?这就是我们下面要说的第3个优化技巧。

3、避免在 where 子句中使用 or来链接条件。

select id from tabel where name = 'UncleToo' or name = 'PHP'

这种情况,我们可以这样写:
select id from tabel where name = 'UncleToo'
union all
select id from tabel where name = 'PHP'

4、少用 in 或 not in。

虽然对于 in 的条件会使用索引,不会全表扫描,但是在某些特定的情况,使用其他方法也许效果更好。如:

select name from tabel where id in(1,2,3,4,5)

像这种连续的数值,我们可以使用 BETWEEN AND,如:
select name from tabel where id between 1 and 5

5、注意 like 中通配符的使用。
下面的语句会导致全表扫描,尽量少用。如:

select id from tabel where name like'%UncleToo%'
或者
select id from tabel where name like'%UncleToo'

而下面的语句执行效率要快的多,因为它使用了索引:
select id from tabel where name like'UncleToo%'

6、避免在 where 子句中对字段进行表达式操作。


select name from table where id/2 = 100

正确的写法应该是:
select name from table where id = 100*2



7、避免在 where 子句中对字段进行函数操作。

select id from table where substring(name,1,8) = 'UncleToo'

select id from table where datediff(day,datefield,'2014-07-17') >= 0

这两条语句中都对字段进行了函数处理,这样就是的查询分析器放弃了索引的使用。正确的写法是这样的:

select id from table where name like'UncleToo%'

select id from table where datefield <= '2014-07-17'
也就是说,不要在 where 子句中的 = 左边进行函数、算术运算或其他表达式运算。


8、在子查询中,用 exists 代替 in 是一个好的选择。

select name from a where id in(select id from b) 
如果我们将这条语句换成下面的写法:
select name from a where exists(select 1 from b where id = a.id)

 

9.Java:子类能够继承父类的私有变量和私有方法?

 

1.关于私有成员变量
无论父类中的成员变量是pirvate、public还是其它类型的,子类都会拥有(继承)父类中的这些成员变量。但是父类中的私有成员变量,无法在子类中直接访问,可以通过从父类中继承得到的protected、public方法(如getter、setter方法)来访问。
个人认为这更好的提现了JAVA特性中的封装,而且符合软件工程的设计思想:低耦合。

 

2.关于静态成员变量
无论父类中的成员变量是静态的、还是非静态的,子类都会拥有父类中的这些成员变量。

 

3.关于被子类覆盖的成员变量
无论父类中的成员变量是否被子类覆盖,子类都会拥有父类中的这些成员变量。

 

10.简述开发中用过的中间件和功能

java中间件就是处理我们数据间交互,连接数据分离后两个系统间的通信,中间件不属于任何一个开发项目,就是让我们对应系统间或者数据库间数据流通无感知。

中间件应用的基本领域与代表:
上面说到java是数据间的中间件,在java web开发中适用的范围主要应该是下面三个领域:

远程过程调用和对象访问中间件:主要解决分布式环境下应用的互相访问问题,这也是支撑应用服务化功能的基础;
例如:RPC:Remote Process Call(远程过程调用中间件)
消息中间件:解决应用之间的消息传递、解耦、异步的问题。
例如:ActiveMQ 是Apache出品,最流行的,能力强劲的开源消息总线。ActiveMQ 是一个完全支持JMS1.1和J2EE 1.4规范的 JMS Provider实现。
数据访问中间件:主要解决应用访问数据库的共性问题的组件
例如:数据访问中间间就是我们使用数据库指定的数据驱动,例如:ODBC JDBC

以 JDBC 为例,数据库本地维护了一个数据访问中间件,我们在访问数据库的时候,配置的地址其实是直接连接到JDBC这个数据访问中间件,如果我们执行查询数据,或者对数据库的操作都是通过JDBC来连接数据库,然后通过JDBC查询完成数据库以后再返回给我们应用程序。作为中间件,查询过程对于我们是不可知的。

 

11.java 中普通类继承,抽象类继承,接口类继承,子类一定要重写父类中的方法吗

简单总结,需要重写的有:

普通类继承抽象类,重写所有抽象类方法;(不包括普通方法)

普通类继承接口,重写所有接口方法。(不包括default关键字修饰的方法)

 

详解见下:

1. 普通类继承,并非一定要重写父类方法。

2. 抽象类继承,如果子类也是一个抽象类,并不要求一定重写父类方法。如果子类不是抽象类,则要求子类一定要实现父类中的抽象方法。

3. 接口类继承。如果是一个子接口,可以扩展父接口的方法;如果是一个子抽象类,可以部分或全部实现父接口的方法;如果子类不是抽象类,则要求子类一定要实现父接口中定义的所有方法。

不一定,关键要看子类是否是抽象类。

    如果子类是非抽象类,则必须实现接口中的所有方法;  

    如果子类是抽象类,则可以不实现接口中的所有方法,因为抽象类中允许有抽象方法的存在!

1、抽象类定义

    抽象类往往用来表征对问题领域进行分析、设计中得出的抽象概念,是对一系列看上去不同,但是本质上相同的具体概念的抽象。通常在编程语句中用 abstract 修饰的类是抽象类。在C++中,含有纯虚拟函数的类称为抽象类,它不能生成对象;在java中,含有抽象方法的类称为抽象类,同样不能生成对象。抽象类是不完整的,它只能用作基类。在面向对象方法中,抽象类主要用来进行类型隐藏和充当全局变量的角色。

2、抽象类特点

    1)抽象类不能实例化。

    2)抽象类可以包含抽象方法和抽象访问器。

    3)不能用 sealed 修饰符修饰抽象类,因为这两个修饰符的含义是相反的。 采用 sealed 修饰符的类无法继承,而abstract 修饰符要求对类进行继承。

    4)从抽象类派生的非抽象类必须包括继承的所有抽象方法和抽象访问器的实际实现。

3、与具体类的比较

    1)抽象类不能直接实例化,并且对抽象类使用 new 运算符会导致编译时错误。虽然一些变量和值在编译时的类型可以是抽象的,但是这样的变量和值必须或者为 null,或者含有对非抽象类的实例的引用(此非抽象类是从抽象类派生的)。

    2)允许(但不要求)抽象类包含抽象成员。

    3)抽象类不能被密封。

4、与接口的比较

    1)相同点

        a、不能实例化;

        b、包含未实现的方法声明;

        c、派生类必须实现未实现的方法,抽象类是抽象方法,接口则是所有成员(不仅是方法包括其他成员)

    2)不同点

        a、类可以实现无限个接口,但仅能从一个抽象(或任何其他类型)类继承,从抽象类派生的类仍可实现接口,从而得出接口是用来解决多重继承问题的。

        b、抽象类当中可以存在非抽象的方法,可接口不能,且它里面的方法只是一个声明必须用public来修饰没有具体实现的方法。

        c、抽象类中的成员变量可以被不同的修饰符来修饰,可接口中的成员变量默认的都是静态常量(static final)。

        d、抽象类是对象的抽象,然而接口是一种行为规范。

转载于:https://www.cnblogs.com/chenshuyong/p/10224738.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值