一、简答题
1. abstract 和final,this,static,private能一起用吗?
abstract 和 final:
final修饰的类是无法被继承的,且final修饰的方法不能被重写
abstract修饰的类一定要有子类(即必须有子类继承抽象类),修饰的方法必须要被子类去实现的(即必须被子类重写其抽象方法)
abstract 和 static:
static修饰的方法是属于类的,它存在于静态区中,static修饰的方法可以直接通过类名调用;
abstract修饰的方法必须要被重写且不能被调用(因为调用抽象方法没有意义)
abstract 和 private:
private修饰的类是不可以被继承的,private修饰的方法不可以被重写
abstract修饰的类必须继承,修饰的方法必须被重写
abstract 和 this:
this:代表的是当前对象,当抽象属性和参数同名时,用this代表当前对象
abstract:是修饰符,可以修饰类和方法。修饰类的时候不能被实例化。修饰的方法没有方法体
2. while和do while的区别?
while: 没有指定次数的循环
do while: 也是没有指定次数的循环,只是无论条件怎样都会先执行一次
3. 构造函数没有返回值能重载吗?为什么?
可以的。构造函数没有返回值类型,也不需要写返回值,因为其是为构建对象的,对象创建完,函数就会执行结束。
4. 简述对象加载机制。
(1)加载
.class
文件进方法区,并进行空间分配(2)如果有静态变量,先默认初始化,显示初始化值
(3)如果有静态代码块(静态代码块优先于主方法执行,优先于构造函数执行),要执行且只执行一次。
(4)通过new关键字在堆内存中开辟空间,并明确首地址。
(5)把对象中的非static属性进行默认初始化
(6)调用相应的构造函数进行初始化
(7)构造函数内部
- 调用父类构造函数super();一个类创建的时候也被动创建了其父类
- 成员变量的显示初始化
- 构造代码块初始化
- 构造函数内容自定义内容初始化
(8)对象初始化完毕后,将地址复制的引用变量
5. 什么是静态代码块、构造代码块、局部代码块?
静态代码块:
就是在代码块之前加上了静态关键字static,这个代码块就称为静态代码块。它优先于主方法执行,优先于构造方法执行,不管创建多少对象,静态代码块只执行一次,可以用于给静态变量赋值;用来给类进行初始化
构造代码块:
直接写在类中的代码块。构造代码块用于给所有对象初始化使用,每创建一个对象就会执行一次构造代码块
局部代码块:
写在方法(局部范围)内的代码块
6. 请说明Overload和Override的区别,Overloaded的方法是否可以改变返回值的类型?
Overload:
函数的重载,在同一个类中允许存在一个以上的同名函数,只要它们的参数个数或者或者参数类型不同即可,这就形成了重载。
Override:
函数的重写,子类中出现与父类一模一样的方法时,会出现覆盖操作,也称为重写、复写或者覆盖。方法的重载和重写都是实现多态的方式,区别在于前者实现的是编译时的多态性,而后者实现的是运行时的多态性。重载发生在一个类中,同名的方法如果有不同的参数列表(参数类型不同、参数个数不同或者二者都不同)则视为重载;重写发生在子类与父类之间,重写要求子类被重写方法与父类被重写方法有相同的返回类型,比父类被重写方法更好访问,不能比父类被重写方法声明更多的异常(里氏代换原则)。重载对返回类型没有特殊的要求。
二、代码题
1. 书写快速排序。
public class Demo{
public static void main(String[] args){
int[] arr = {5,3,-5,6,15,8};
quickSort(arr,0,6);
System.out.println("快速排序后的序列为:" + arr);
}
// 快速排序
public static void quickSort(int[] arr,int L,int R){
// 递归出口
if(L > R){
return;
}
// 序列的第一个值设为key
int key = arr[L];
// 左指针
int i = L;
// 右指针
int j = R;
while(i < j){
// 只要j指向的值比key小的话,j就会停下来,由左指针i继续走
while(i < j && arr[j] >= key){
j--;
}
// 只要i指向的值比key大的话,i就会停下来,由右指针j继续走
while(i < j && arr[i] < key){
i++;
}
// 当左指针i和右指针j没有相遇时
if(i < j){
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
// 进行完一轮快速排序之后会有,这一轮的key会固定
// 将左右指针相遇指向的值与key进行交换即可
// 然后对key值进行更新,每一轮的key值是这个序列的第一个值
arr[L] = arr[i];
arr[i] = key;
// 对左右子序列进行排序
quickSort(arr,L,i-1);
quickSort(arr,i+1,R);
}
}
2. 书写冒泡排序。
public class Demo{
public static void main(String[] args){
int[] arr = {5,3,-5,6,15,8};
BubbleSort(arr);
}
// 冒泡排序
public static void BubbleSort(int[] arr){
for(int i = 0;i <arr.length;i++){
for(int j = 0;j < arr.length-i-1;j++){
if(arr[j] > arr[j+1]){
int temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
System.out.println(Arrays.toString(arr));
}
}
3. 二维数组求和。
public class Demo{
public static void main(String[] args){
int[][] arr = {{1,2},{5,6}};
getSum(arr);
}
// 二维数组求和
public static void getSum(int[][] arr){
int sum = 0;
for(int i = 0;i < arr.length;i++){
for(int j = 0;j < arr[i].length;j++){
sum += arr[i][j];
}
}
System.out.println("二维数组的和为:" + sum);
}
}
4. 编写单例模式。
(1)饿汉模式
public class Single{
// 私有化构造方法
private Single(){}
// 创建全局私有操作的对象
private static Single sg = new Single();
// 对外提供对象
public static Single getInstance(){
return sg;
}
}
(2)懒汉模式
public class Single{
// 私有化构造方法
private Single(){}
// 创建全局私有操作的对象
private static Single sg;
// 对外提供对象
public static Single getInstance(){
if(sg == null){
sg = new Single();
}
return sg;
}
}
5. 创建一个类,但是限制其能创建的对象个数不大于5。(一个类最多只能创建5个对象)
public class Demo{
// 统计产生对象的个数
private static int i = 1;
private static Demo d;
// 私有化构造方法
private Demo(){}
// 限制创建对象的方法
public static Demo getInstance(){
if(i < 6){
d = new Demo();
i++;
return d;
}
return null;
}
// 测试
public static void main(String[] args){
// 创建Demo对象
Demo d1 = Demo.getInstance();
Demo d2 = Demo.getInstance();
Demo d3 = Demo.getInstance();
Demo d4 = Demo.getInstance();
Demo d5 = Demo.getInstance();
Demo d6 = Demo.getInstance();
System.out.println(d1);
System.out.println(d2);
System.out.println(d3);
System.out.println(d4);
System.out.println(d5);
System.out.println(d6);
}
}
三、算法题
1.求 1+2+…+n ,要求不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句(A?B:C)。+
public class Demo{
public static void main(String[] args){
System.out.println(getSum(100));
}
public static int getSum(int n){
boolean flag = (n>1 && (n += getSum(n-1))>0);
return n;
}
}
2.字符串的左旋转操作是把字符串前面的若干个字符转移到字符串的尾部。请定义一个函数实现字符串左旋转操作的功能。
比如,输入字符串"abcdefg"和数字2,该函数将返回左旋转两位得到的结果"cdefgab"。
示例 1:
输入: s = “abcdefg”, k = 2
输出: “cdefgab”
示例 2:
输入: s = “lrloseumgh”, k = 6
输出: “umghlrlose”
限制:
1 <= k < s.length <= 10000
public class Demo{
public static void main(String[] args){
String str = "abcdefg";
spinString(str,2);
}
// 字符串旋转
public static void spinString(String str,int k){
String newstr = str.substring(0,k);
String systr = str.substring(k,str.length());
str = systr + newstr;
System.out.println("旋转后的字符串为:" + str);
}
}