java面试

java面试可能会遇到的问题

33.数组的排序算法有哪些?如何实现?(冒泡排序,选择排序,插入排序,快速排序)
冒泡排序:
按升序排列。首先比较a[1]与a[2]的值,若a[1]大于a[2]则交换两者的值,否则不变。再比较a[2]与a[3]的值,若a[2]大于a[3]则交换两者的值,否则不变。再比较a[3]与a[4],依此类推,最后比较a[n-1]与a[n]的值。处理一轮后,a[n]的值一定是这组数据中最大的。再对a[1]~a[n-1]以相同方法处理一轮,依此类推。共处理n-1轮后a[1]、a[2]、……a[n]就以升序排列了。
优点:稳定,比较次数已知; 它的时间复杂度为O(n^2)
缺点:慢,每次只能移动相邻两个数据,移动数据的次数多。

	int[] arrInt={85,6,20,45,63,12,58,21};		
			for (int i = 0; i < arrInt.length; i++) {
				for (int j = i+1; j < arrInt.length; j++) {		
					if(arrInt[i]>arrInt[j]){
						int temp=arrInt[i];
						arrInt[i]=arrInt[j];
						arrInt[j]=temp;
					}	
				}

选择排序:
按升序排列。首先比较a[1]与a[2]的值,若a[1]大于a[2]则交换两者的值,否则不变。再比较a[1]与a[3]的值,若a[1]大于a[3]则交换两者的值,否则不变。再比较a[1]与a[4],依此类推,最后比较a[1]与a[n]的值。这样处理一轮后,a[1]的值一定是这组数据中最小的。再将a[2]与a[3]~a[n]以相同方法比较一轮,依此类推。共处理n-1轮后a[1]、a[2]、……a[n]就以升序排列了。 选择排序是不稳定的排序方法
优点:比较次数与冒泡排序一样,数据移动次数比冒泡排序少; 它的时间复杂度为O(n^2)
缺点:相对之下还是慢。

int[] arrInt = { 85, 6, 20, 45, 63, 12, 58, 21 };
		for (int i = 0; i < arrInt.length; i++) {
			int temp;
			int min = arrInt[i];
			for (int j = i + 1; j < arrInt.length; j++) {
				if (min > arrInt[j]) {
					min = arrInt[j];
					temp = arrInt[i];
					arrInt[i] = arrInt[j];
					arrInt[j] = temp;
				}
			}
		}

插入排序:
假定这个数组的序是排好的,然后从头往后,如果有数比当前外层元素的值大,则将这个数的位置往后挪,直到当前外层元素的值大于或等于它前面的位置为止.这具算法在排完前k个数之后,可以保证a[1…k]是局部有序的,保证了插入过程的正确性.
优点:稳定,快; O(n^2)
缺点:比较次数不一定,比较次数越少,插入点后的数据移动越多,特别是当数据总量庞大的时候,但用链表可以解决这个问题。

	int[] arrInt = { 85, 6, 20, 45, 63, 12, 58, 21 };
		int temp;
     for (int i = 1; i < arrInt.length; i++) {
			temp = arrInt[i];
			int j = i;
			while (j > 0 && arrInt[j - 1] > temp) {
				arrInt[j] = arrInt[j - 1];
				j--;
			}
			arrInt[j] = temp;
		}

快速排序:
快速排序是冒泡排序的改进版,是目前已知的最快的排序方法。设要排序的数组是A[0]……A[N-1],首先任意选取一个数据(通常选用第一个数据)作为关键数据,然后将所有比它小的数都放到它前面,所有比它大的数都放到它后面,这个过程称为一趟快速排序。快速排序不是一种稳定的排序算法,也就是说,多个相同的值的相对位置也许会在算法结束时产生变动。
优点:极快,数据移动少;O(nlog n) 期望时间,O(n^2) 最坏情况
缺点:不稳定。

public class Hello {
	public static void main(String[] ars) {
		int arr[]={2,76,45,4,323,545,34,23,36,6,5};
		quickSort(arr);
		System.out.println(Arrays.toString(arr));
	}
	public static void sort(int[] arr, int low, int hight) {
		int i, j, index;
		if (low > hight) {
			return;
		}
		i = low;
		j = hight;
		// 在这里,用数组的第一个记录作为基准数
		index = arr[i];
		// 进行扫描
		while (i < j) {
			while (i < j && arr[j] >= index)
				j--;
			if (i < j)
				// 用比基准小的记录替换低位记录
				arr[i++] = arr[j];
			while (i < j && arr[i] < index)
				i++;
			if (i < j)
				// 用比基准大的记录替换高位记录
				arr[j--] = arr[i];
		}
		arr[i] = index;// 将基准数值替换回arr[i]
		sort(arr, low, i - 1);
		sort(arr, i+1, hight);
	}
	public static void quickSort(int[] arr) {
		sort(arr, 0, arr.length - 1);
	}
}	

34.什么是类、对象、属性和方法?

答:类(class):
具有相同属性和行为的一组对象集合,它为属于该类的所有对象提供了统一的抽象描述

对象:
是一个具有明确行为的具体实体、具有行为和状态,有着清晰的边界。对象在面向对象系统中用来描述客观事物的一个实体,它是构成系统的一个基本单位。以面向对象的眼光来看待现实世界,现实世界中每一个具体事物都可看作一个对象,对象不仅可以是有形的实体,也能表示无形(抽象)的规则、计划或事件。例:狗、手机、自行车、飞机、银行利息的计算方法…
把对象所有特征(属性)称之为对象的状态,方法称之为行为。

属性:
对象的一种内在或独有的性质、质量或特征,可以构成一个独一无二的对象
例:颜色:黑色,重量:222kg…这些都可以称作为属性。

方法:
是一个对象根据它的状态改变和消息传递所采取的行为动作和作出的反应,代表了对象对外的可见、可测试的动作。
在程序中,方法是描述用于解决复杂问题的一组代码组成所组成的某个功能单元,通常由一系列数据成员和一些操作组成,是用来实现类的行为,一个方法通常只完成某一项具体功能

35.什么是包?有什么好处?
包:是类的容器,(通俗点就是包就是类所在的文件夹组织java文件的),如果没有指定包名,所有的示例都属于一个默认的无名包,Java中的包一般均包含相关的类,将功能相似的一些java类放在同一个包中。
好处:
更好的组织类、调用,防止在一个空间下出现类重名啊这些情况;表明类之间的层次关系,

36.解释定义: 普通类 抽象类 接口?
接口:是用来接收数据的一个端口,用来给不同类或前后端做通信用的。通俗点就是说接口就是给某个事物对外提供了一些功能和服 务声明。接口的使用者只需要使用这些功能和服务就行,不需要关心具体的实现,如果是接口的实现者,则需要实现这些具体 的功能和服务
1、接口中定义方法和属性;不能有构造器,不能实例化,可继承多个接口,可以用abstract修饰
2、方法只有声明,没有方法体;
3、属性默认为public static fianl的,且必须有初始化值;
4、interface关键字来定义接口类
Eg:[修饰符] interface 接口名{
常量声明,方法声明

}
抽象类:使用了关键词abstract声明的类叫作“抽象类”。如果一个类里包含了一个或多个抽象方法,类就必须指 定成abstract(抽象)。“抽象方法”,属于一种不完整的方法,只含有一个声明,没有方法主体。
1、抽象类定义方法和属性;可以有构造方法,不能实例化
2、抽象类可以继承抽象类,且只能继承一个;抽象类也可以继承一个普通类;
3、可以定义普通方法,但必须有方法体;
4、属性可以没有初始化值
普通类:就是类是具备某些共同特征的实体的集合。
1、普通类可以继承普通类,且只能继承一个普通类;
2、普通类可以被抽象类继承;
3、普通类能同时实现多个接口
抽象类与普通类的区别:
普通类可以去实例化调用;抽象类不能被实例化,因为它是存在于一种概念而不非具体。
普通类和抽象类都可以被继承,但是抽象类被继承后子类必须重写继承的方法,除非自类也是抽象类。
抽象类与接口的区别:
1、概念不一样。接口是对动作的抽象,抽象类是对本质的抽象。
抽象类表示的是,这个对象是什么。接口表示的是,这个对象能做什么。
2、使用不一样:
a.抽象类和接口都是用来抽象具体对象的,但是接口的抽象级别最高
b.抽象类可以有具体的方法 和属性,接口只能有抽象方法和不可变常量
c.抽象类主要用来抽象类别,接口主要用来抽象功能.
d.抽象类中,且不包含任何实现,派生类必须覆盖它们。接口中所有方法都必须是未实现的。
e.接口是设计的结果 ,抽象类是重构的结果
3、使用方向:当关注一个事物的本质的时候,用抽象类;当关注一个操作的时候,用接口。

38.什么是多态?有什么好处? 写一个多态案例?

答:多态就好比“龙生九子,各有不同”
多态就是一个类,内部构造一样,但里面的属性等可以是多种多样的,
eg:颜色:可以是黑色也可以是白色…
也就是说,一个对象多种形态,多态指在一般类中定义的属性和行为,具有不同的表现
好处:
1.可替换性:多态对已存在的代码具有可替换性。
2.可扩充性:多态对代码具有可扩充性。增加新的子类不影响已存在类的多态性、继承性,以及其他 特性的运行和操作。实际 上新加子类更容易获得多态功能。  
3.接口性:多态是超类通过方法签名,向子类提供了一个共同接口,由子类来完善或者覆盖它而实现的。
4.灵活性:它在应用中体现了灵活多样的操作,提高了使用效率。  
5.简化性:多态简化了对应用软件的代码编写和修改过程。

案例:

public class People{
protected String name;
protected int age;
public static void main(String[] args) {
	People man=new Man("小白");
	man.say();
	
	People woman=new Woman("小红");
	woman.say();
}

public void say(){
	System.out.println("大家好:我叫"+name+",今年"+age+"岁!");
}
}

class Man extends People{
	public String sex;
	public Man(String name) {
		super();
		this.sex = "男";
		this.name=name;
	}
	//重写父类方法
	public  void say(){
		System.out.println(name+"说:我是一个有责任的"+sex+"人");	
	}	
}

class Woman extends People{
	public String sex;
	public Woman(String name) {
		super();
		this.sex = "女";
		this.name=name;
	}
	//重写父类方法
	public  void say(){
		System.out.println(name+"说:我是一个漂亮的"+sex+"人");	
	}
}

39.什么是内部类?有什么好处?Static Nested Class 和 Inner Class的不同?
答:内部类就是在一个类的内部再定义一个类
Static Nested Class 和 Inner Class不同在于一个是静态类 ,一个是非静态类,
然后调用方法就所不同,下面是案例
54.如何调用内部类中的方法?

1.使用static可以声明一个内部类,可以直接在外部调用

public class Outer {        // 定义外部类
private static String info = "hello world";  // 定义外部类的私有属性
public static void main(String[] args) {
	new Outer.Inner().print(); // 调用外部类的fun()方法
}
static class Inner {    // 使用static定义内部类为外部类
public void print() {  // 定义内部类的方法
System.out.println(info);  // 直接访问外部类的私有属性
}
}
public void fun() {   // 定义外部类的方法
new Inner().print();  // 通过内部类的实例化对象调用方法
}
}

2.不使用statc声明一个内部类 ,使外部调用

public class Outer { // 定义外部类
private String info = "hello world";	 // 定义外部类的私有属性
public static void main(String args[]) {
		Outer out = new Outer();  // 外部类实例化对象
		Outer.Inner in = out.new Inner();    // 实例化内部类对象
		in.print(); // 调用内部类的方法
		}	
class Inner {         // 定义内部类
public void print() {    // 定义内部类的方法
System.out.println(info);  // 直接访问外部类的私有属性
}
}
public void fun() {    // 定义外部类的方法
new Inner().print();   // 通过内部类的实例化对象调用方法
}
}

3.在方法中定义内部类 ,使外部调用

class Outer { // 定义外部类
private String info = "hello world"; // 定义外部类的私有属性
public static void main(String args[]) {
new Outer().fun(30); // 调用外部类的方法
}
public void fun(final int temp) {// 定义外部类的方法
class Inner {// 在方法中定义的内部类
public void print() {// 定义内部类的方法
System.out.println("类中的属性:" + info);// 直接访问外部类的私有属性
System.out.println("方法中的参数:" + temp);
}
}
new Inner().print();// 通过内部类的实例化对象调用方法
}
}	

43.什么是方法重写?为什么需要方法重写?什么是方法重载?为什么需要方法重载?

答:
方法的重写:
是相对于继承来说的,子类重写父类中的方法,其中方法名、返回类型,参数类型和参数个数都和父类中的方法一样,只是方法内部中的构造和实现结果不同

为什么需要方法重写:
重写是对类中方法的扩充,因为继承用的是父类的东西,重写则不仅得到父类的东西,同时也加入了自己的东西

方法的重载:
是相对于在本类中而言的,是指方法名相同,但方法参数列表不同。参数可以是个数和类型不一样

为什么需要方法重载:
扩展父类的功能,如果有两个类A和B,继承C,那么在C的方法只需要定义A和B相同的功能,而在各个子类中扩展子类具体的实现。

45.构造器是否可以被重写?能否被重载?

答:构造器是可以被重载的,
继承中是不继承构造方法的,所以更不能被重写

46.static修饰的方法能否在子类中重写?

答可以的,
Eg:

public class Outer { 
public static void main(String[] args) {
	A a=new A();
	  a.text();
	B b=new B();
	  b.text();
}
}
class  A{
	public static void text(){
		System.out.println("父类中的static方法....");
	}
}
class B extends A{
public static void text(){
	System.out.println("父类中的static方法重写....");
	}
}

输出结果为:
父类中的static方法…
父类中的static方法重写…

47.在定义类时,何时需要重写Object类中的toString()方法?

答:在要你想要输出什么格式的时候就可以重写toString()方法;
Eg:
原本的toString()方法
public String toString() {
return “Outer [name=” + name + “, age=” + age + “]”;
}
如果此时你想要返回的结果不是上面的样式,就可以重写该方法

public String toString() {
return “姓名:” + name + “年龄:” + age;
}

56.Java中异常处理的方式有哪些?常见的RuntimeException异常有哪些?

  1. try catch:
    try{} 中放入可能发生异常的代码。catch{}中放入对捕获到异常之后的处理。其中catch中e.printStackTrace()作用就是,在控制台打印程序出错的位置及原因。try{} 中放入可能发生异常的代码。catch{}中放入对捕获到异常之后的处理。其中catch中e.printStackTrace()作用就是,在控制台打印程序出错的位置及原因。
    只有try块中代码发生异常才会走到 catch块。
    有的异常捕获会加上finally,无论try块中异常有无捕获finally块中最后都会执行,除非try块代码中有 system.exit(0)(system.exit(0)的作用是退出虚拟机)。
    2.Throw
    Throw是语句抛出异常,出现于函数内部,用来抛出一个具体异常实例,throw被执行后面的语句不起作用,直接转入异常处理阶段,
    Eg:
public class Ex{
public static void main(String[] args) {
	  try {
		  throw new A("异常");	
	} catch (Exception e) {
		e.printStackTrace();
	}    	  
}
}
class  A extends Exception{
	public A(String str){
		super(str);
	}
}

throws是函数方法抛出异常,一般写在方法的头部,用来抛出一些异常,本身不进行解决,抛给方法的调用者进行解决(try catch)
Eg:

public class Ex{
public static void main(String[] args) {
	 try {
		 System.out.println(method());	
	} catch (Exception e) {
		e.printStackTrace();
	}    	  
}
static int method()  throws Exception{	
	int a=10;
	int b=0;
	int c;
	c=a/b;
	return c;
}
}

58.try-catch-finally语句块各部分的执行顺序如何?
答:
1、除了以下2种情况外,不管有木有出现异常,finally块中代码都会执行;
a、程序未进入try{}块的执行,如在try之前出现运行时异常,程序终止。
b、程序进入到try{}和catch{}块的执行,但是在try{}或者catch{}块碰到了System.exit(0) 语句,jvm直接退出。finally{}块不会执行
2、当try和catch中有return时,finally仍然会执行;
3、finally是在return后面的表达式运算后执行的(此时并没有返回运算后的值,而是先把要返回的值的引用地址保存起来,而不管finally中的代码怎么样,最后返回的都是这个引用地址(或者说这个引用地址指向的对象),
而这个返回值在finally中会被不会被改变要分以下情况)。
若这个返回值是基本数据类型(int,double)或者不可变类对象(如String,Integer),则不管finally中的代码怎么样,返回的值都不会改变,仍然是之前保存的值,若这个值是可变类对象,则会改变。
4、finally中最好不要包含return,否则程序会提前退出,返回值不是try或catch中保存的返回 值,而是finally中的return值。

60.throw和throws的区别?
答:
throw是语句抛出一个异常。
语法:
throw (异常对象);
throw e;
throws是方法可能抛出异常的声明。(用在声明方法时,表示该方法可能要抛出异常)
语法:
(修饰符)(方法名)([参数列表])[throws(异常类)]{…}
public void text(int a) throws Exception1,Exception3{…}
区别:
throw语句用在方法体内,表示抛出异常,由方法体内的语句处理。
throws语句用在方法声明后面,表示再抛出异常,由该方法的调用者来处理。
throws主要是声明这个方法会抛出这种类型的异常,使它的调用者知道要捕获这个异常。
throw是具体向外抛异常的动作,所以它是抛出一个异常实例。

两者都是消极处理异常的方式(这里的消极并不是说这种方式不好),只是抛出或者可能抛出异常,但是不会由函数去处理异常,真正的处理异常由函数的上层调用处理。

71.String、StringBuffer和StringBuilder的区别?

答:三者共同之处:都是final类,不允许被继承,主要是从性能和安全性上考虑的,因为这几个类都是经常被使用 着,且考虑到防止其中的参数被参数修改影响到其他的应用。

StringBuffer是线程安全,可以不需要额外的同步用于多线程中;
StringBuilder是非同步,运行于多线程中就需要使用着单独同步处理,但是速度就比StringBuffer快;
StringBuffer与StringBuilder两者共同之处:可以通过append、indert进行字符串的操作。
String实现了三个接口:Serializable、Comparable、CarSequence
StringBuilder只实现了两个接口Serializable、CharSequence,相比之下String的实例可以通过compareTo 方法进行比较,其他两个不可以。
区别:
1、首先说运行速度,或者说是执行速度,在这方面运行速度快慢为:StringBuilder > StringBuffer > String
【String最慢的原因:String为字符串常量,而StringBuilder和StringBuffer均为字符串变量,即String 对象一旦创建之后该对象是不可更改的,但后两者的对象是变量,是可以更改的。】

  1. 再来说线程安全
      在线程安全上,StringBuilder是线程不安全的,而StringBuffer是线程安全的.
      如果一个StringBuffer对象在字符串缓冲区被多个线程使用时,StringBuffer中很多方法可以带有 synchronized关键字,所以可以保证线程是安全的,但StringBuilder的方法则没有该关键字,所以不能保证 线程安全,有可能会出现一些错误的操作。所以如果要进行的操作是多线程的,那么就要使用StringBuffer, 但是在单线程的情况下,还是建议使用速度比较快的StringBuilder。
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值