1.1 面向对象的特性有哪些方面?面向对象编程有什么特点? 3
1.3.3 String、StringBuilder、StringBuffer区别? 4
1.14 try、catch、finally代码块执行顺序 8
1.15.1 ArrayList、Vector、LinkedList比较 8
1.15.2 Array 和 ArrayList 的比较? 9
1.15.3 HashMap、HashTable、HashSet区别? 9
1.16 final、finally、finalize的区别? 9
1.17.2 tcp的建立连接的3次握手和断开连接的4次握手 10
1.19.4 线程的wait()方法和sleep()方法? 11
2.10 如何给 Spring 容器配置提供元数据(bean的配置)? 14
- 抽象:忽略一个主题中与当前目标无关的那些方面,以便更充分地注意与当面目标有关的方面,抽象并不打算了解全部问题,而是选择其中的一部分,忽略细节部分
- 封装:把过程和数据包围起来,对数据的访问只能通过方法来访问
- 继承:子类继承父类,保留父类的属性,开扩新的东西
- 多态:重载和重写,重载是可以有相同的方法名,不同的参数类型;重写是对父类的方法重写
特点:
- 开发时间短,效率高,可靠性高,由于面向对象的可重用性,可以在应用程序当中大量采用成熟的类库,从而缩短了开发的时间
- 应用程序更易于维护、更新和升级。继承和封装使得应用程序的修改带来的影响更加局部化
自动装箱:Java编译器在基本数据类型和对应的包装类之间的转换,叫做自动装箱,例如:int转Integer,double转Double;反之就是自动拆箱
-
- switch语句能否作用在byte上?能否用在long上?能否用在string上?
能用在byte上,不能用在long和string上。
- byte、char、short、int四种基本类型以及它们的包装类(需要Java5.0/1.5以上版本支持)都可以用于switch语句。
- long、float、double、boolean四种基本类型以及它们的包装类(在Java所有版本中)都不能用于switch语句。
- enum类型,即枚举类型可以用于switch语句,但是要在Java5.0(1.5)版本以上才支持。
- 所有类型的对象(包括String类,但在Java5.0/1.5以上版本中,该项要排除byte、char、short、int四种基本类型对应的包装类)都不能用于switch语句
-
- 值传递和引用传递
- java语言参数之间只有值传递,包括按值调用和按引用调用。 一个方法可以修改传递引用所对应的变量值,而不能修改传递值调用所对应的变量值。
- 按值调用:包括八大基本数据类型都是按值调用。传值的时候,也就是说方法得到的是所有参数值的一个拷贝。
- 按引用调用:数组、对象。传值时候,传递的是引用地址的拷贝,但是都是指向同一个对象。
- String是不可变类(final and Immutable),传递String时,也只是改变了String参数的指向地址,原来的String指向的地址仍然不变。
-
- Java内部类
-
- Java类中方法的重写需要注意的原则?
方法的重写(override)两同两小一大原则:
不是,String是类类型
基本的数据类型有八种:
- 整型: byte(8位)、 short(16位)、 int(32位)、 long(64位)
- 字符型: char, 只能存放一个字符
- 浮点型: float(32位)、 double(64位)。 注: 默认的小数类型是double
- 布尔型: true、 false
不可以,因为String类有final修饰符,而final修饰的类是不能被继承的
- String的对象是不可变的,也可以理解为常量,显然是线程安全的
- StringBuilder和StringBuffer均为字符串变量,对象可变,StringBuilder为单线程但线程不安全,StringBuffer是多线程且线程安全
- 效率上 StringBuilder > StringBuffer > String
打开关闭连接数据库这种和数据库的交互是很耗费系统资源的,尤其是客户端量增加的时候,需要不断的去打开和关闭数据库的连接,可以建立很多的数据库连接来放到一个连接池中,当有客户端请求时,数据库的连接请求从连接池中提取,当操作完毕后,也将连接放回数据库连接池中,以满足以后更多的请求
- public: 表示该数据成员、成员函数是对所有用户开放的,所有用户可以直接进行调用
- private:表示私有成员变量,出了自己class能调用,其他类不能调用,只能通过封装函数来调用
- protected:表示受保护成员变量,除了所属类、子类、同一包下的类都可以调用,其他包的类都不能调用
面的循环语句前定义一个标号如ok,利用break ok可以终止多个嵌套循环
被static修饰的变量称为类变量,不属于任何一个对象,一个类不管创建了多少个对象,静态变量在内存中只有一个拷贝,让多个实例对象共享静态变量;实例化变量必须依附于某个实例化的对象,需要创建对象后才可以访问。
不正确,因为精度不准确,应该用强制转换类型float f=3.4f或float f=(float)3.4。
在Java中,没小数点的默认是int,有小数点的默认是double
编译器可以自动向上转型,double转float是不能自动转型的
- ==比较的是栈中的值(对象在栈中存放方式为堆内存地址)==在比较基本数据类型时比较的是值,而==在比较两个对象时比较的是两个对象是否指向同一个内存地址值
- equals通常被覆盖为比较两个对象的值,所以通常用来比较两个对象的内容是否相同,Java中所有的类都继承了Object类,而Object类中的equals方法是返回的是==的判断,也就是说,如果比较的对象没有重写过equals方法的话,比较的仍是==。
- Integer是int的包装类,int是java的一种基本数据类型
- Integer变量必须实例化后使用,而int变量不需要
- Integer实际是对象的引用,当new一个Integer时,实际上是生成一个指针指向对象,所以两个new的Integer变量是不相等的,而int则是直接存储数据值
- Integer的默认值是null,int的默认值是0
- 插入排序:
- 数组下标为0的位置不放数据,作用哨兵数据存放
- 从数组的第二个数据开始遍历,如果遍历到的数据A比前一位的数据小,说明该数据A需要往前移动,将该数据A放到哨兵位置
- 从数据A下标开始往前遍历,将前面数据后移,找到合适位置后将哨兵数据插入到该位置
- 希尔排序
- 冒泡排序
- 快速排序
- 直接选择排序
- 堆排序
- 归并排序
- 分配排序
- 如果类的方法声明中使用abstract修饰符,表明该方法是一个抽象方法,它需要在子类去实现
- 如果一个类中存在抽象方法,则该类为抽象类,也必须使用abstract修饰,并不能实例化
- 如果子类只覆盖了部分的抽象方法,那么该子类还是一个抽象类
- 与final修饰符不能共存,因为final不能有子类,而抽象类一定是父类
- 与private关键字不能共存,不能被子类所知道,就无法被复写,而抽象方法就是需要被复写
参数 | 抽象类 | 接口 |
默认的方法实现 | 有默认的方法实现 | 接口完全是抽象的。它根本不存在方法的实现 |
实现 | 子类使用extends关键字来继承抽象类。如果子类不是抽象类的话,它需要提供抽象类中所有的声明方法的实现 | 类使用关键字implements来实现接口,它需要提供接口中所有声明方法的实现 |
构造器 | 抽象类中可以有构造器 | 接口不能有构造器 |
与正常Java类的区别 | 除了不能实例化抽象类之外,它和普通Java类没有任何区别 | 接口是完全不同的类型 |
访问修饰符 | 抽象方法可以有public、protected和default这些修饰符 | 接口默认修饰符是public。不可以使用其他的修饰符 |
多继承 | 抽象方法可以继承一个类和实现多个接口 | 接口只可以继承一个或多个其他接口 |
添加新方法 | 如果你往抽象类中添加新方法,你可以提供默认的实现方法,不需要修改继承该抽象类的类的实现方法 | 往接口添加新方法,需要在实现该接口的类也要实现接口的新加的方法 |
Java反射机制是在运行状态时,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意的一个类,都能够调用它的任意一个方法;能找出方法名,变量名,方法,修饰符,类型,方法参数等等所有信息
反射的核心类有四个:Class、Constructor、Field、Method
在执行try、catch中的return语句之前一定会先执行finally的代码块,如果finally中有return语句,就会直接执行finally中的return方法
Vector、ArrayList都是以类似数组的形式存储在内存中,LinkedList则以链表的形式进行存储
- 线程同步
Vector为同步线程,线程安全,ArrayList、LinkedList线程不同步,线程不安全
效率上ArrayList > Vector
- List中的元素有序、允许有重复的元素,Set中的元素无序,不允许有重复元素
- LinkedList链表在插入、删除操作方面高效,查找低效,因为链表需要移动指针;ArrayList、Vector数组在查找方面高效,在添加或删除操作方面较低效,因为数组需要移动数据
- ArrayList扩容时默认扩大原来的50%+1, Vector扩容时默认扩大为原来的2倍,所以在内存开销方面ArrayList要优于Vector
- Array可以包含基本数据类型和对象类型,ArrayList只能包含对象类型
- Array是大小固定的,ArrayList的大小是动态变化的
- ArrayList提供了更多的特性方法,例如:addAll(), removeAll() 等
- HashMap是一个数组和链表的结合体
- HashMap实现Map接口,HashSet实现Set接口
- HashMap存储的是键值对,HashSet仅仅存储一个键(对象),两者都不能含有相同的键值,都不是线程安全的
- HashMap是非同步的(线程不安全的),HashTable是同步的(线程安全的)
- HashMap的key和value都可以为null,而HashTable的key,value都不能为null
- HashMap的默认扩容为原来的50%+1,HashTable的默认扩容为原来的2倍
-
-
- Collection和Map接口
-
- final:如果final修饰类,则该类不能作为父类被继承;如果修饰方法或变量,可以保证他们在使用的时候不会被改变
- finally:在异常处理操作的时候,提供finally块来执行任何的清除操作,finally语句始终会被执行,主要是用来释放资源,比如I/O缓冲区,数据库连接
- finalize:这个方法是垃圾收集器确认一个对象没有被引用时对这个对象调用的,它是在Object类中定义的,所以所有的类都继承了它。
- tcp是面向连接的流传输控制协议,具有高可靠性,确保传输数据的正确性,有验证重发机制,因此不会出现丢失或乱序
- udp是无连接的数据传输服务,不对数据进行检查和修改,也无需等待对方的应答,但是会出现丢失,重复,乱序,但具有较好的实时性,udp段结构比tcp段结构简单,网络开销小
- tcp的建立时候需要3次握手,断开连接需要4次握手;udp不需要经过握手,所以udp在效率上比较快
- tcp面向字节流传输;udp面向数据报的传输
- 连接握手:
- 第一次握手:客户端连接到服务端
- 第二次握手:服务端接收客户端连接请求后,向客户端发送一个消息
- 第三次握手:客户端向服务端发送第二次握手的确认消息
- 断开连接握手:
- 第一次握手:断开连接的一端发送close请求
- 第二次握手:另一端接收断开连接的请求后发送消息对close进行确认
- 第三次握手:发送断开连接的一端进入time_wait状态
- 第四次握手:发送断开连接的一端对返回消息进行确认
WebService 就是一个部署在Web服务器上的,它向外界暴露出一个能够通过Web请求进行调用的API
在有并发线程A、B的程序执行前的时候,有synchronized 的关键字的代码块中,如果线程A正在执行程序,则线程B必须等待线程A执行完毕才能接着执行程序。synchronized作用于两种情况:synchronized方法和synchronized块
- 修饰非静态代码块:
一个线程A访问对象中的同步代码块时,其他线程也想访问该对象的同步代码块时必须阻塞等待,直到线程A执行完毕释放锁; 但是其他线程可以访问该对象的非同步代码块
- 修饰静态代码块和修饰类
在静态方法或类上加上 synchronized 关键字,则是整个类里面的所有对象共用一个锁
- wait方法会释放锁,一般配合notify方法使用,将线程挂起,其他线程可以访问
- sleep方法不会释放锁,使线程挂起,其他线程仍需等待当前线程执行完毕
注:通过子类调用父类的静态方法,子类不会被初始化
类中的静态块会在整个类加载过程中的初始化阶段执行,而不是在类加载过程中的加载阶段执行。初始化阶段是类加载过程中的最后一个阶段,该阶段就是执行类构造器<clinit>方法的过程,<clinit>方法由编译器自动收集类中所有类变量(静态变量)的赋值动作和静态语句块中的语句合并生成,一个类一旦进入初始化阶段,必然会执行静态语句块。所以说,静态块一定会在类加载过程中被执行,但不会在加载阶段被执行。
加载—>实例化—>服务—>销毁
当客户端第一次请求时,Web容器先判断是否存在Servlet对象,如果不存在,则调用init方法(只调用一次)创建servlet对象,然后调用service方法处理客户端请求,当Web容器关闭或者Servlet对象要从Web容器中删除时调用destroy方法(只调用一次)
- init() : 在servlet的生命周期中,init() 方法仅会执行一次,它是在服务器装载servlet时执行的,负责初始化servlet对象
- service() : 负责响应客户端的请求;每当一个客户端请求一个httpServlet对象时,都要调用一次service()方法
- destroy():仅执行一次,在服务器端停止且卸载Servlet时执行该方法。
Spring是一个企业级开元的Java轻量级框架,可以应用于所有的Java应用程序的开发,但在Web 方面中比较有针对性,凭借着spring的两大特性,依赖注入和Aop编程简化项目的开发,并且在后期项目的维护方面提供了很好的便利性
- 类(bean)的建立
- 设置属性(属性注入)
- BeanNameAware接口的setBeanName()可以获取正在被实例化的bean的id的值,配置文件中有几个User类型的bean,就会打印几个id值
- BeanFactoryAware的setBeanFactory()
- ApplicationContextAware接口
- BeanPostProcessor的processBeforeInitialization()
- Bean定义文件中定义init-method初始化
- BeanPostProcessors的processaAfterInitialization()
- DisposableBean的destroy()
Aop是面向切面编程,主要的作用是关注程序的执行过程,在java方法被调用前,AOP机制能自动进行方法的拦截,允许方法在调用之前,调用后,以及调用异常时添加特定的代码来完成需要的功能,主要在安全,事务,日志等的集中式处理。
mysql为例:先下载mysql-connect的驱动包,然后在spring配置文件中的配置 dataSource里的driverClass的值为com.mysql.jdbc.driver
如果控制器是使用单例形式,且controller中有一个私有的变量a,所有请求到同一个controller时,使用的a变量是共用的,即若是某个请求中修改了这个变量a,则,在别的请求中能够读到这个修改的内容。
- 原子性:表示事务包含的所有数据操作要么全部成功,要么全部失败回滚;
- 一致性:事务必须使数据库从一个一致性状态转移到另一个一致性状态,也就是说一个事务执行之前和执行之后都必须处于一致性的状态;
- 隔离性:多个并发事务之间要隔离,正在执行的事务不能被其他数据库的事务干扰
- 持久性:
保证数据的完整性和安全性,比如一个业务中事务A和事务B都要进行,如果事务A执行失败时候而同时事务B也执行完毕了,但是没有提交,这时候有异常的时候就要将事务回滚,回到修改前,保证数据的一致性和完整性。
spring beans表示受到spring管理的对象,具体来说,它是被spring框架容器初始化、配置和管理的对象,beans在spring的配置文件中定义,也可以利用spring的注解来定义,所有的bean在容器中初始化,然后注入到应用程序中。
- Xml文件配置<bean />
- 注解方式 @Service @Controller @Component
- 基于Java的配置 @bean @configuration
Mybatis的优势
1、MyBatis可以进行更为细致的SQL优化,可以减少查询字段;
2、MyBatis容易掌握,而Hibernate门槛较高。
Hibernate优势
1、Hibernate的DAO层开发比MyBatis简单,Mybatis需要维护SQL和结果映射;
2、Hibernate对对象的维护和缓存要比MyBatis好,对增删改查的对象的维护要方便;
3、Hibernate数据库移植性很好,MyBatis的数据库移植性不好,不同的数据库需要写不同SQL;
4、Hibernate有更好的二级缓存机制,可以使用第三方缓存。MyBatis本身提供的缓存机制不佳。
工厂模式:ApplicationContext.xml 中用到
模板模式:
代理模式:spring 的 aop编程
单例模式:保证一个类仅有一次实例
策略模式:
构造器模式:
- 用户发送请求,请求被spring 的 dispatcherServlet捕获
- DispatcherServlet对用户请求的url进行解析,根据解析出来的资源URI调用处理器映射器HandlerMapping获取Handler配置的所有相关的对象,以HandlerExecutionChain对象的形式返回
- DispatcherServlet根据返回获得的Handler对象,选择一个合适的处理器适配器HandlerAdapter,然后执行拦截器的处理
- Handler处理请求信息和业务信息,执行完毕后,向DispatcherServlet返回一个ModelAndView对象
- 根据返回的ModelAndView对象,选择一个合适的ViewResolver返回给DispatcherServlet
- ViewResolver根据model和view,来渲染视图
- 将渲染后的数据返回给客户端(用户)
保证一个类仅有一个实例,并提供一个访问它的全局访问点
优点:在内存中只有一个实例,减少了内存的开销
public class SingleObject {
//创建 SingleObject 的一个对象
private static SingleObject instance = new SingleObject();
//让构造函数为 private,这样该类就不会被实例化
private SingleObject(){}
//获取唯一可用的对象
public static SingleObject getInstance(){
return instance;
}
public void showMessage(){
System.out.println("Hello World!");
}
}
一个节点含有的子树的个数称为该节点的度
- 树的度
最大的节点的度成为树的度
- 一个长度为100的循环链表,指针A和指针B都指向了链表中的同一个节点,A以步长为1向前移动,B以步长为3向前移动,一共需要同时移动多少步A和B才能再次指向同一个节点__50__。
解释:因为有100个节点,可以先假设先都在节点1,B经过33步刚刚到达节点100,而A在34,第34步B到达节点3,A在35,所以接下来是3+3n=35+n,所以n=16,所以总共=34+16=50
- 有一个8升的水杯,另外分别有一个3升和5升的空水杯,问怎么从中取得4升水和7升水,不能借用任何其它工具
解释:假定A为8升水杯,B为3升水杯,C为5升水杯
从A倒满B,B再倒满C ,A再倒满B, A、B、C中水量分别为2、1、5;
从C倒满A后,A杯得到7升水,A、B、C中水量为7、1、0
然后
从B全部倒进C、A倒满B,A、B、C中水量为4、3、1
A杯得到4升水
- 杨辉三角
n*(n-1)*(n-2)*...*(n-k+1)/(1*2*3*...*k) 其中n为行数,k为列的偏移量,公式为第n行偏移量k的值
- 水仙花数
水仙花数是指一个 3 位数,它的每个位上的数字的 3次幂之和等于它本身(例如:1^3 + 5^3+ 3^3 = 153)
- 256,269,286,302,(n=?)
因为:
256 : 2+5+6 = 13;
269 = 256+13;
所以:
302: 3+2 = 5;
n = 302 + 5 = 307
- 以下对TCP和UDP描述正确的是(D)
- TCP不能提供数据的可靠性
- UDP能够保证数据库的可靠性
- TCP数据传输效率高于UDP
- UDP数据传输效率高于TCP
解释: 因为UDP传输数据不需要经过三次握手,而TCP需要经过三次握手
- 给定一个整数数组和一个目标值,找出数组中和为目标值的两个数
每个输入只对应一种答案,且同样的元素不能被重复利用
- 查找字符串数组中的最长公共前缀
如果不存在公共前缀,返回空字符串“”
所有输入只包含小写字母a-z
解释:
/**
* Created by root on 2014-12-03.
* Write a function to find the longest common prefix string amongst an array of strings.
* 找到一个字符串数组的最长公共前缀
* 相当于 abcdef abcd 的最长公共前缀是 abcd
* 本题目的思路是最长公共字符串肯定不会比整个数组中最短的长,顶多相等。
* 那么我们假设第一个是公共串,让他和后面的挨个对比,如果它比后面的短,那么就逐个字符对比,如果共同的比当前的短则截断
* 这样遍历一次即可获得最短公共串
*/
public String longestCommonPrefix(String[] strs){
if(strs == null || strs.length==0) return "";
String prifex = strs[0]; // 默认将第一个认为是最长共同
for(int i=1;i<strs.length;i++){
// 将当前最长共同字符串和当前数组中的对比,把小的那个作为长度
int len = prifex.length()>strs[i].length() ? strs[i].length():prifex.length();
int j=0;
for(j=0;j<len;j++){
// 逐个字符比较,不等的时候退出
if(prifex.charAt(j)!=strs[i].charAt(j))
break;
}
// 退出的j即当前的最小,整个遍历结束后就是整个的最小了
prifex = prifex.substring(0,j);
}
return prifex;
}
- 给定一个只包括 ‘(‘ , ‘)’ 的字符串,判断字符串是否有效。
有效字符串需要满足:
- 左括号必须用相同类型的右括号闭合
- 左括号必须以正确的顺序闭合
解释: 利用栈结构,遇到左括号将左括号入栈,遇到右括号,栈顶出栈一个左括号;如果遇到右括号,栈顶没有元素了,则判断无效
- 输入是一个无符号整数,返回其二进制表达式中数字位数为 1 的个数
- 给定一个二叉树,试找出这棵树的最大深度
二叉树的深度为根节点到最远叶子节点的距离。
/**
* Definition of TreeNode:
* class TreeNode {
* public:
* int val;
* TreeNode *left, *right;
* TreeNode(int val) {
* this->val = val;
* this->left = this->right = NULL;
* }
* }
*/
class Solution {
public int maxDepth(TreeNode *root) {
if(root==NULL){
return NULL;
}
int left=maxDepth(root->left);
int right=maxDepth(root->right);
return (left>right)?(left+1):(right+1);
}
};
- 删除链表中等于给定值val的所有节点
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
public class Solution {
/**
* @param head a ListNode
* @param val an integer
* @return a ListNode
*/
public ListNode removeElements(ListNode head, int val) {
// Write your code here
if(head==null) return head;
ListNode p=head,q=head.next;
while(q!=null){
if(q.val==val){
p.next=q.next;
q=q.next;
}else {
p=p.next;
q=q.next;
}
}
if(head.val==val)
head=head.next;
return head;
}
}
- 集合中有多个元素,每个元素对应不同的权重,从中一次性抽取n个不重复的元素。
- 添加主键索引
ALTER TABLE `table_name` ADD PRIMARY KEY ( `column` )
- 添加唯一索引
ALTER TABLE `table_name` ADD UNIQUE (`column`)
- 添加普通索引
ALTER TABLE `table_name` ADD INDEX index_name ( `column` )
- 添加全文索引
ALTER TABLE `table_name` ADD FULLTEXT (`column`)
- 添加多列索引
ALTER TABLE `table_name` ADD INDEX index_name ( `column1`, `column2`, `column3` )
- 数值类型:tinyint、smallint、mediumint、int或integer、bigint、float、double、decimal
- 日期和时间类型: date、time、year、datetime、timestamp
- 字符串类型: char、varchar、tinyblob、tinytext、blob、text、mediumblob、mediumtext、longblob、longtext
- 存储过程的实现功能要复杂些,而函数实现的功能针对性比较强
- 函数必须有返回值,且只能返回一个值;存储过程有返回值,但是能返回结果集
- 函数可以嵌入sql语句中使用,比如select 函数名(参数值);存储过程通过call语句调用,如call 存储过程名
- 函数的参数传入类似于in参数;存储过程的参数in、out、inout
-
- 优化SQL
- 选取最适用的字段
- 优化SQL
- 尽量将字段的值的宽度设置小一点,比如varchar(10)可以解决存储的不要用varchar(255),同样的可以用int解决的别用bigint
- 字段的值尽量设置not null约束,在查询的时候就不用比较null值,利于提高查询效率
-
-
- 使用索引
-
索引能提高数据查询的效率
- 索引一般用在join、where判断和orderby排序的字段上,尽量不要用在大量重复或存储宽度过大的字段上
- 索引不是越多越好,索引对insert 和 update语句有影响,因为在进行insert或update可能会重建索引,一个表中的索引最好不要超过6个
-
- 事务
-
尽量避免使用大事务操作,提高数据库系统的高并发性
-
-
- Select查询
-
查询避免使用 *, 尽量列出需要查询出来的字段,不要返回用不到的字段