记笔试面试那些事儿
Use 'Ctrl+F' to find your aim
1. CoreJava
1.1 BasicJava
JVM特性
- 平台无关性. Java语言的一个非常重要的特点就是与平台的无关性。而使用Java虚拟机是实现这一特点的关键。一般的高级语言如果要在不同的平台上运行,至少需要编译成不同的目标代码。而引入Java语言虚拟机后,Java语言在不同平台上运行时不需要重新编译。Java语言使用模式Java虚拟机屏蔽了与具体平台相关的信息,使得Java语言编译程序只需生成在Java虚拟机上运行的目标代码(字节码),就可以在多种平台上不加修改地运行。Java虚拟机在执行字节码时,把字节码解释成具体平台上的机器指令执行。
JVM内存分配
- 基本数据类型、变量和对象的引用都是在栈分配的
- 堆内存存放由new创建的对象与集合
- 类变量(static修饰的变量):程序在一加载的时候就在堆中为类变量分配内存,堆中的内存地址存放在栈中
- 实例变量:当你使用java关键字new的时候,系统在堆中开辟并不一定是连续的空间分配给变量,是根据零散的堆内存地址,通过哈希算法换算为一长串数字以表征这个变量在堆中的”物理位置”,实例变量的生命周期 — 当实例变量的引用丢失后,将被GC(垃圾回收器)列入可回收“名单”中,但并不是马上就释放堆中内存。
- 局部变量:声明在方法里或代码块里,执行到它的时候,就在内存中开辟内存,一旦局部变量脱离作用域,该内存会立即释放
多态
允许不同对象对同一消息做出响应,即同一消息可以根据发送对象的不同而采用多种不同的行为方式(发送消息就是函数调用)。
主要有以下优点:
- 可替换性:多态对已存在代码具有可替换性
- 可扩充性:增加新的子类不影响已存在的类结构
- 接口性:多态是超类通过方法签名,向子类提供一个公共接口,由子类来完善或者重写它来实现
- 灵活性
- 简化性
怎么实现多态:
- 接口实现
- 继承父类、重写方法
- 同一类中进行方法重载
PS:虚拟机是如何实现多态的:
动态绑定技术(dynamic binding),执行期间判断所引用对象的实际类型,根据实际类型调用对应的方法。
基本数据类型
类型 | 位数 | 字节数 |
---|---|---|
boolean | ||
byte | 1 | 8 |
char | 2 | 16 |
short | 2 | 16 |
int | 4 | 32 |
long | 8 | 64 |
float | 4 | 32 |
double | 8 | 64 |
Java中创建对象的几种方式
- 采用new
- 通过反射
- 采用clone
- 通过序列化
接口和抽象类的区别!!!
比较 | 抽象类 | 接口 |
---|---|---|
默认方法 | 有默认的方法实现 | java8之前,接口中不存在方法的实现 |
实现方法 | 如果子类不是抽象类,需要通过抽象父类中所声明方法的实现 | 用implements来实现接口,需要提供接口所声明的实现 |
构造器 | 有 | 没有 |
修饰符 | 四种都可以 | 默认为public,其它不能 |
多继承 | 一个子类只存在一个父类 | 一个子类可以存在多个接口 |
添加新方法 | 向抽象类中添加新方法,可以提供默认的实现,因此可以不修改子类现有的方法 | 往接口中添加新方法,则子类中需要实现该方法 |
其它 | 抽象类当然是类啦 | 接口,顾名思义… |
Object中有哪些公共方法
equals()
clone()
getClass()
notify()
,notifyAll()
,wait()
toString
java中
==
和equals()
的区别
- == :为运算符,用于比较两个变量是否相等
- equals:是Object类的方法,用于比较两个对象是否相等
- 换句话说:基本类型比较用
==
,比较的是他们的值。默认下,对象用==
比较时,比较的是内存地址,如果需要比较对象内容,需要重写equal方法。
& 和 &&的区别
- &是位运算符,不具备短路功能;&&是逻辑运算符,具备短路功能
final, finalize, finally
- final:修饰符,可以修饰变量、方法和类
- finalize: 方法,在对象被回收之前调用的方法,给对象自己一次复活的机会,但何时调用finalize方法没有保证
- finally:关键字,常与try-catch搭配使用(try-finally也行),用于异常的处理,finally块中代码一定会执行,不论try块还是catch块执行
final的用法
上文 提到了final,下面列述其用法:
- 被final修饰的类,不可以被继承
- 被fianl修饰的方法,不可以被重写
- 被final修饰的变量,不可以被改变
- 被final修饰的引用,引用不可变,引用指向的内容可变
- 被final修饰的常量,在编译阶段会存入常量池中(那static修饰的常量放哪里呢?)
- 被final修饰的方法,JVM会尝试将其内联,以提高运行效率
1.2 AdvanceJava
HashMap与HashTable的区别
- HashMap:
①键和值可以为空
②HashMap的方法不能同步
③HashMap会重新计算hashcode - HashTable:
①键非空唯一,值非空
② HashTable的方法是同步的
③HashTable使用对象的hashcode
ArrayList与LinkedList的区别
- ArrayList:
①数组
②查询快于LinkedList,存取慢于LinkedList
③支持随机访问 - LinkedList:
①双向链表
②由于链表结构,存取(插入删除)快,查询慢
③不支持随机访问
- PS:倘若使用下标访问一个元素,ArrayList的时间复杂度是O(1),LinkedList是O(n).
1.3 Java8
lambda表达式
基本结构:() -> {}
作用:匿名内部类的简化版,是函数式接口
就举几个栗子吧:
list.sort((o1, o2) -> {o1 - 02});
map.entrySet().forEach(System.out::println);
map.forEach((k,v)->System.out.println(k+" : "+v));
Comparator和Comparable的区别
-
Comparable 接口用于定义对象的自然顺序,而 comparator 通常用于定义用户定制的顺序。Comparable 总是只有一个,但是可以有多个 comparator 来定义对象的顺序。
2. Spring
2.1 Spring
Spring框架的设计模式
- 工厂设计模式
BeanFactory与ApplicationContext创建bean对象 - 代理设计模式
SpringAOP功能的实现 - 单例设计模式
Spring中的bean默认都是单例的 - 包装器设计模式
可以选择连接多个数据库 - 观察者模式
Spring事件驱动模型 - 适配器模式
SpringAOP的增强或通知(Advice)
SpringMVC用到了适配器配置Controller - 模板方法模式
以Template结尾的对数据库操作的类 - … …
Spring中的bean生命周期
- Bean容器找到配置文件中Spring Bean的定义。
- Bean容器利用Java Reflection API创建一个Bean的实例。
- 如果涉及到一些属性值,利用set()方法设置一些属性值。
- 如果Bean实现了BeanNameAware接口,调用setBeanName()方法,传入Bean的名字。
- 如果Bean实现了BeanClassLoaderAware接口,调用setBeanClassLoader()方法,传入ClassLoader对象的实例。
- 如果Bean实现了BeanFactoryAware接口,调用setBeanClassFacotory()方法,传入ClassLoader对象的实例。
- 与上面的类似,如果实现了其他*Aware接口,就调用相应的方法。
- 如果有和加载这个Bean的Spring容器相关的BeanPostProcessor对象,执行postProcessBeforeInitialization()方法。
- 如果Bean实现了InitializingBean接口,执行afeterPropertiesSet()方法。
- 如果Bean在配置文件中的定义包含init-method属性,执行指定的方法。
- 如果有和加载这个Bean的Spring容器相关的BeanPostProcess对象,执行postProcessAfterInitialization()方法。
- 当要销毁Bean的时候,如果Bean实现了DisposableBean接口,执行destroy()方法。
- 当要销毁Bean的时候,如果Bean在配置文件中的定义包含destroy-method属性,执行指定的方法。
单例Bean的作用域
单例(singleton)
原型(prototype)
请求(request)
会话(session)
全局(global-session)
2.2 SpringMVC
SpringMVC的流程
- 请求者发送request请求,DispatcherServlet处理请求,并向HandlerMapping请求解析查找handler
- HandlerMapping返回一个执行链(Interceptor):preHandle/postHandle/afterHandle
- DispatcherServlet请求适配器执行Handler
- HandlerAdapter将handler交给Handler/Controller去执行
- Controller返回一个ModelAndView对象(Model是返回的数据对象,View是逻辑上的View)
- ViewResolver会根据逻辑View去查找实际的View
- DispatcherServlet把返回的Model传给View(视图渲染)
- 把View返回给请求者
Spring中的MVC模式基本概念
Java Bean/Dao(Model)+JSP(View)+Servlet(Controller)
- Service层(处理业务/逻辑)
- Dao层(数据库操作)
- Entity层(实体类)
- Controller层(控制层)
2.3 Spring注解
- @Autowired注解的作用
自动扫描该注解下的类,将其自动装配,其作用是代替getter/setter方法与bean属性中的property - @Qualifier
用于多个实现类(接口)的装配 - @Resource
@Resource后面没有任何内容,默认通过name属性去匹配bean,找不到再按type去匹配。
指定了name或者type则根据指定的类型去匹配bean。
指定了name和type则根据指定的name和type去匹配bean,任何一个不匹配都会报错。 - @Service
- 声明某个类是一个bean,才能使用@Autowired将其作为成员变量自动注入
- 省略了.xml中的配置bean操作
- 其在类中的id为类名首字母小写
- @Scope(“prototype”)
Spring默认产生的bean是单例的,如果不想使用单例,xml文件里面可以在bean里面配置scope属性。
注解也一样,配置@Scope即可,默认是"singleton"即单例,"prototype"表示原型即每次都会new一个新的出来。 - @Component 与 @Bean的区别
- @Component作用于类、@Bean作用于方法
- @Component定义要扫描的路径,会自动侦测以及自动装配到Spring容器中、@Bean标有该注解的方法中产生这个bean
- @Bean比@Component自定义性更强
3. Another
3.1 XML
解析XML的方法
DOM、SAX、PULL
- DOM: 消耗内存:先把xml文档都读到内存中,然后再用DOM API来访问树形结构,并获取数据。这个写起来很简单,但是很消耗内存。要是数据过大,手机不够牛逼,可能手机直接死机
- SAX: 解析效率高,占用内存少,基于事件驱动的:更加简单地说就是对文档进行顺序扫描,当扫描到文档(document)开始与结束、元素(element)开始与结束、文档(document)结束等地方时通知事件处理函数,由事件处理函数做相应动作,然后继续同样的扫描,直至文档结束。
- PULL: 与 SAX 类似,也是基于事件驱动,我们可以调用它的next()方法,来获取下一个解析事件(就是开始文档,结束文档,开始标签,结束标签),当处于某个元素时可以调用XmlPullParser的getAttributte()方法来获取属性的值,也可调用它的nextText()获取本节点的值。
- 2019/11/28 😐 😛 |第一次发布文章|
- 2019/12/02 😄 😮 |更新了CoreJava部分,添加了Another主标签块|
- 2019/12/03 |更新了CoreJava部分|
- 2020/01/01 |停止更新|