当前位置:文档之家› java基础经典面试题汇总

java基础经典面试题汇总

面试题汇总
1,jre与jdk的区别?
jvm:java虚拟机 用于解释并执行java程序的应用软件 不具有跨平台性
jre:jre=jvm+类库 java运行环境
jdk:jdk=jre+开发工具(包括打包工具和编译工具) 供开发人员使用


2,简述环境变量path和classpath的作用?
path:方便应用程序在任何路径中都可以运行的运行 记录的是执行应用程序的路径
classpath:记录的是执行class程序的路径 方便java程序的运行
如何配置:临时配置:在dos中,path=路径名;%path%
想要在原有环境值基础上添加新值:通过%变量名%操作符获取原有环境变量的值,set path=新值;%path%
永久配置:我的电脑-->属性-->高级设置-->环境变量-->path-->把bin的
目录复制进来。 配置技巧:新建--变量名:JAVA_HOME 变量值:bin的路径
编辑path-------%变量名%。


3,简述classpath环境变量值结尾处是否需要加分号,有什么区别?
系统先找classpath中的路径
Classpath=路径名 只找配置中的路径,不会去找当前目录 (建议写法)
Classpath=路径名; 先找配置中的路径,如果没有会去当前目录中找
Classpath=.;路径名 . 表示当前路径
原因:如果加了分号,会有意想不到的结果,不利于开发。假设配置的路径没有
.class文件,就会到当前目录去找,得到的结果不是想要的结果,所以建议不要写。


4,i++与++i的区别?
int a=3,b ; b=a++; temp=a(先将a进行临时存储) ; a=a+1(自增); b=temp(将临时的值赋值给b)
int a=3,b; b=++a; //a=a+1;将a赋给b

5,class OperateDemo2
{
public static void main(String[] args)
{
/*
赋值运算符。
= += -= *= /= %=
*/
//int x,y,z;
//x=y=z=3;
int a = 3;//右边赋给左边。
a+=4;//将左右两边的和赋给左边。 a = a + 4;
short s = 4;
//s = s + 5;//编译失败。s+5 s会自动提升为int型与5相加,结果为int型,而s是short型,会报错
s+=5;//编译通过,会做自动转换。

System.out.println("Hello World!");
}
}
6,byte b=6;6是默认的int型 占4个字节
由于前面是byte 所以系统会自动检查 如果b的取值在-128~127 就将int型转换为byte型(去掉三个字节)
byte b=2; int i=5; i=i+b; 通过 i=5
byte b=3 b=b+5 报错 why--> b+5是变量 值不确定
所以jvm不会将b+5进行自动转换
long l=12345678999 会报错 正确写法 long l=1234566899L (12349859099默认是int型
但123456777989的值超过了int的取值范围,所以要在后面加L,否则会精度会失去,
当7899在int范围内时,不需加L long l=78888; l占8个字节 78888是int型
占4个字节 byte b=8 b是byte型占1个字节 8是int型占4个字节 )

float f=3.1 会报错 正确写法 float f=3.1f (3.1是double型 精度更高
所以会报错; double d=3.1f 是可以的 3.1f的精度小于double的精度)

7,int i = 3;i = i++;System.out.println("i="+i); (第一步:先将i进行临时存储temp=3;
第二步:i=i+1;第三步:将临时变量赋给i,即i=temp)

8,&和&&的区别:
&:两边都参与运算。
&&:当左边为false。右边不参与运算。

9,需求:如果往有序的数组中插入一个元素并继续保证有序,问如何获取该位置?
思路:利用二分查找法来获得元素的位置,
步骤:1,通过角标先获取中间角标上元素。
2,让该元素和要找的数据比较。
3,如果要插入的数大了,缩小范围,要找的范围应该是 中间的角标+1---尾角标。
如果要插入的数小了,要找的范围 头角标---中间角标-1;
4,不断如此重复,就可以找到元素对应的角标。如果要插入的数与数组中的某个元素相等
则获取此角标,如果不等,则返回此时头角标的值。

10,class Test
{
int x = 4;
public static void main(String[] args)
{
Test t = new Test();
t.x = 7;
show(new Test());
System.out.println("x="+t.x);
}
public static int show(Test t)
{
t.x = 9;
return t.x;
}
}

//自己画图。
class Test
{
public static void main(String[] args)
{
int[] arr = new int[2];
show(arr);
System.out.println(arr[0]);
}
public static void show(int[] arr)
{
arr[0]++;
}
}






10,class Array2Demo
{
public static void main(String[] args)
{
//二维数组。
/*
int[][] arr = new int[3][2];

System.out.println(arr);// [[I@e6f7d2//二维数组实体。
System.out.println(arr[0]);//[I@3e0ebb//一维数组实体。
System.out.println(arr[0][0]);//0 一维数组中的元素。
*/
//
int[][] array = new int[3][];//明确了二维数组的长度,没有明确具体的一维数组。
System.out.println(array);//[[I@3e0ebb
System.out.println(array[0]);//null
System.out.println(array[0][0]);//NullPointerException

}
}
11,静态代码块 构造代码块 局部代码块 的作用与区别

静态代码块:特点:随着类的加载而执行,而且只执行一次,并且优先于主函数执行用于给类进行初始化。
格式 static{ 语句; }
作用:用来给类进行初始化

构造代码块:作用:给对象进行初始化。对象一建立就运行,而且优先于构造函数执行。
与构造函数的区别:构造代码块是给所有的对象进行统一初始化,而构造函数是给对应的对象初始化

局部代码块:在方法里面
作用:控制局部变量的生命周期,里面的代码块一执行完,就失效。好处:节省内存。

12,class Demo
{
Demo d = new Demo();
Demo()
{
System.out.pri

ntln("demo run");
}
}
main()
{
new Demo();
}
画图解释 栈溢出

13,单例设计模式的两种写法与思路,和解决的问题。


14,class Fu
{
int x = 5;
{
System.out.println("fu num="+x);
}
Fu()
{
x = 8;
System.out.println("fu num="+getNum());
}
int getNum()
{
return x;
}
void show()
{
System.out.println(getNum());
}
}
class Zi extends Fu
{
int y = 4;
{
System.out.println("zi num="+y);
}
Zi()
{
y = 9;
}
int getNum()
{
return y;
}
}

//画图求解。

class ExtendsTest
{
public static void main(String[] args)
{
new Zi().show();
}
}
//答案见图
E:\传智播客面试班--0620java基础班\课堂 ---------视频\day08 ExtendsTest.java

15,接口vs抽象类:(面试重点)
1,抽象类和类之间存在的是单继承(is a)关系,但是只能是单继承
接口和类之间存在的是实现(like a)关系,可以多实现
2,抽象类中是可以定义非抽象方法的,提供给子类直接使用
接口中的方法都是抽象的,子类必须全部实现才可以使用

16,编译看左边,(★★★★★)
1,成员变量:多态调用时,编译和运行都参考引用型变量所属的类中的成员变量,编译和运行看等号的左边
2,成员函数:多态调用时,编译参考的是引用型变量所属的类,运行时参考的是对象所属类,
编译看左边,运行看右边。(动态绑定,动态绑定到当前对象上)
3,静态函数:多态调用时,编译和运行都参考引用型变量所属的类中的成员变量,
编译和运行看等号的左边(静态绑定:绑定到类上)

17,
class Fu
{
int num = 9;
void show()
{
System.out.println(this.num);//this=0x0088//this=new Zi();//Fu f = new Zi(); f.num;
}
}
class Zi extends Fu
{
int num = 4;
}

class Test
{
public static void main(String[] args)
{
Fu f = new Zi();//0x0088
f.show();


/*
面试题。两个匿名内部类有区别吗?为什么?
答:有 第二个编译不通过 show()是匿名子类的特有方法,Object中没有show()方法,第二匿名对象obj是父类
引用对象,不能访问子类的特有方法
*/
new Object()
{
public void show()
{
System.out.println("show run");
}
}.show();
Object obj = new Object()
{
public void show()
{
System.out.println("show run");
}
};
obj.show();
}
}

18,interface Inter
{
void method();
}
class Demo
{
static Inter show()//为什么此处该为 Inner会报错?????
{
class Inner implements Inter
{
public void method()
{
System.out.println("haha");
}
}
return new Inner();
}
}
class InnerClassTest2
{
public static void main(String[] args)
{
Demo.show().method();
/*
Demo.show

():show()方法是定义在Demo类中的静态方法
Demo.show().method():可知show()的返回值类型是对象,是什么对象呢?要访问接口中的method()方法
,所以要定义内部类去实现接口,返回值类型为Inter (注意不能定义为内部类类型的返回值)
.java
InnerClassTest2.java:18: 错误: 无法取消引用void
Demo.show().method(); //show()的返回值不对
InnerClassTest2.java:7: 错误: 找不到符号
static Inner show() //返回值类型不存在 改正:内部类不能在这里出现,此时内部类还不会加载到内存中
符号: 类 Inner
位置: 类 Demo
^
*/

}
}

19,
interface Inter
{
void method();
}
class Demo
{
//代码补足,建议可以使用匿名内部类。
static Inter show()
{
//返回一个Inter接口的子类对象。
return new Inter()
{
public void method(){}
};
}

}


class InnerClassTest
{
public static void main(String[] args)
{
Demo.show().method();
/*
Demo.show():show在被Demo类调用,说明show是Demo类中的静态方法。
Demo.show().method():show()方法运行完还可以调用method说明show方法运行完返回一个对象。
这个对象是什么类型呢?能调用method方法的对象必然是Inter类型。
*/
}
}


异常处理&多线程总结

20,创建线程的两种方式的区别?
第一种、继承Thread类。
1,继承Thread类。
2,覆盖run方法。
3,创建子类对象就是创建线程对象。
4,调用Thread类中的start方法就可以执行线程。并会调用run方法。
创建线程的第二种方式。实现Runnable接口。
1,定义一个类实现Runnable。
2,覆盖Runnable接口中的run方法,将线程要运行的任务代码存储到该方法中。
3,通过Thread类创建线程对象,并将实现了Runnable接口的对象作为Thread类的构造函数的参数进行传递。
4,调用Thread类的start方法,开启线程。

实现Runnble接口的好处:
1,避免了继承Thread类的单继承的局限性。
2,Runnable接口出现更符合面向对象,将线程单独进行对象的封装。
3,Runnable接口出现,降低了线程对象和线程任务的耦合性。
所以,以后创建线程都使用第二种方式。

调用start和调用run方法的区别?
调用start会开启线程,让开启的线程去执行run方法中的线程任务。
直接调用run方法,线程并未开启,去执行run方法的只有主线程。

21,//同步嵌套,死锁。

class Task implements Runnable
{
private boolean flag;
Task(boolean flag)
{
this.flag = flag;
}
public void run()
{
if(flag)
{
while(true)
synchronized(MyLock.LOCKA)
{
System.out.println("if.....locka");
synchronized(MyLock.LOCKB)
{
System.out.p

rintln("if.....lockb");
}
}
}
else
{
while(true)
synchronized(MyLock.LOCKB)
{
System.out.println("else.....lockb");
synchronized(MyLock.LOCKA)
{
System.out.println("else.....locka");

}
}
}
}
}

class MyLock
{
public static final Object LOCKA = new Object();
public static final Object LOCKB = new Object();
}




class DeadLockTest
{
public static void main(String[] args)
{
//创建线程任务。
Task t1 = new Task(true);
Task t2 = new Task(false);
new Thread(t1).start();
new Thread(t2).start();
}
}

22,Wait()和sleep()的区别?
相同:可以让线程处于冻结状态
不同点:1,wait()可以指定时间,也可以不指定
Sleep()必须指定时间
2,wait()释放cpu资源,释放锁
Sleep()释放cpu资源,不释放锁

23,一个子线程循环5次,然后主线程循环10次。
如此交替执行,共反复20次。
一t0 1 一t0 2 一t0 3 一t0 4 一t0 5
一main 1 一main 2 一main 3 一main 4 一main 5 一main 6一main 7一main 8一main 9一main 10
二t0 1t0 2t0 3t0 4t0 5
main 1main 2main 3main 4main 5main 6main 7main 8main 9main 10

思路:子线程和主线程要定义同一把锁,并要用到for嵌套循环,外循环控制交替执行的次数,
内循环控制每次交替打印的次数,当子线程运行时,子线程的一次循环没结束,main就不
能运行 ,当子线程运行完时,唤醒main线程,在main线程运行的过程中,子线程不能运行,直到for循环结束,唤醒zi线程
通过新锁可以解决此问题。
import java.util.concurrent.locks.*;
class Print implements Runnable//定义一个实现Runnable的子类
{
Lock lock;
Condition zi;
Condition main;
Print(Lock lock,Condition zi,Condition main)//进行初始化
{
this.lock=lock;
this.zi=zi;
this.main=main;
}
public void run()//复写run方法
{
lock.lock();//使用锁
try
{
for(int count=1;count<21;count++)//控制循环的次数,也是交替的次数
{
while (PrintDemo.flag)
{
try{zi.await();}catch (InterruptedException e){}
}
for (int i=1;i<6 ;i++ )
{
System.out.println("第"+count+"次"+"t0 "+i);
}
PrintDemo.flag=true;
main.signal();

}
}
finally{
lock.unlock();
}
}
}
class PrintDemo
{
static boolean flag;
public static void main(String[] args)
{
Lock lock=new ReentrantLock();//创建锁
Condition zi=lock.newCondition();//创建锁的对象,用来操作子线程
Condition main=lock.newCondition();//创建锁的对象,用来操作main线程
Print p=new Print(lock,zi,main);
Thread t=new Thread(p);
t.start();
lock.lock();
try
{
for(int cou

nt=1;count<21;count++)//控制循环的次数,也是交替的次数
{
while (!flag)
{
try{main.await();}catch (InterruptedException e){}
}
for (int i=1;i<11 ;i++ )
{
System.out.println("第"+count+"次"+"mian "+i);
}
flag=false;
zi.signal();
}
}
finally{
lock.unlock();
}

}
}

集 合

24,定义功能,请除去ArrayList集合中的重复元素。


package cn.itcast.list.test;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class ArrayListTest2 {
public static void main(String[] args) {

List list = new ArrayList();

list.add("abc1");
list.add("abc4");
list.add("abc2");
list.add("abc1");
list.add("abc4");
list.add("abc4");
list.add("abc2");
list.add("abc1");
list.add("abc4");
list.add("abc2");

System.out.println(list);
singleElement2(list);
System.out.println(list);
}

/**
* 去除重复元素方式二:
* 思路:
* 1,最后唯一性的元素也很多,可以先定义一个容器用于存储这些唯一性的元素。
* 2,对原有容器进行元素的获取,并到临时容器中去判断是否存在。容器本身就有这个功能,判断元素是否存在。
* 3,存在就不存储,不存在就存储。
* 4,遍历完原容器后,临时容器中存储的就是唯一性的元素。
*
*/
public static void singleElement2(List list){

//1, 定义一个临时容器。
List temp = new ArrayList();

//2, 遍历原容器。
for (Iterator it = list.iterator(); it.hasNext();) {
Object obj = (Object) it.next();

//3, 在临时容器中判断遍历到的元素是否存在。
if(!temp.contains(obj)){
//4,如果不存在,就存储到临时容器中。
temp.add(obj);
}

}
//5, 将原容器清空。
list.clear();
//6, 将临时容器中的元素都存储到原容器中。
list.addAll(temp);

}
/**
* 定义功能。去除重复元素。
*/
public static void singleElement(List list){
for(int x=0; xObject obj_x = list.get(x);
for(int y=x+1; y
if(obj_x.equals(list.get(y))){
list.remove(y);
y--;
}
}
}

}


}

25, 请通过LinkedList实现一个堆栈,或者队列数据结构。

package cn.itcast.list.linkedlist;

import java.util.LinkedList;

public class LinkedListTest {

/**
* @param args
*/
public static void main(String[] args) {

/*
* 练习: 请通过LinkedList实现一个堆栈,或者队列数据结构。
* 堆栈: 先进后出。 First In Last Out FILO.
* 队列: 先进先出。First In First Out FIFO.
*
*/

//1,创建自定义的队列对象。
MyQueue queue = new MyQueue();

//2,添加元素。
queue.my

Add("abc1");
queue.myAdd("abc3");
queue.myAdd("abc4");
queue.myAdd("abc5");

//3,获取所有元素。先进先出。
while(!queue.isNull()){
System.out.println(queue.myGet());
}

}

}
/*
* 描述一个队列数据结构。内部使用的是LinkedList。
*/
class MyQueue{

private LinkedList link;
MyQueue(){
link = new LinkedList();
}

/**
* 添加元素的方法。
*/
public void myAdd(Object obj){
//内部使用的是linkedlist的方法。
link.addFirst(obj);
}

/**
* 获取队列元素的方法。
*/
public Object myGet(){
return link.removeLast();
}

/**
* 集合中是否有元素的方法。
*/
public boolean isNull(){
return link.isEmpty();
}
}

26,"bwaerctyxacecrtdcvr"
获取字符串中每一个字母出现的次数。要求结果格式:a(2)b(1)d(3)......

package cn.itcast.test;

import java.util.Map;
import java.util.TreeMap;

public class Test {

/**
* @param args
*/
public static void main(String[] args) {

/*
* 作业:"bwaerctyxacecrtdcvr"
* 获取字符串中每一个字母出现的次数。要求结果格式:a(2)b(1)d(3)......
* 思路:发现存在对应关系,首先想到使用map集合,字符串应转换成字符数组,怎样将字符数组
* 存入map集合呢?首先要对数组进行for循环,遍历数组,要保证字母的唯一性,应将字母当做键
* 存入map中,字母出现的次数,当做键值存入集合中,怎样获得字母出现的次数呢?想到使用计数器
* 通过get()方法获取键值,并判断是否为空,如果为空说明此字母第一次出现,否则,将获得的键值
* 加1存入map中。
* 作业:
* hashmap中存储员工。
* treeMap中对员工进行姓名或者年龄的排序。
*
*/
String str="bwaercty563xacecr,/itdcvr";
String str_count=huoQu(str);//1,通过一个方法实现此功能
System.out.println(str_count);
}

public static String huoQu(String str) {
// TODO Auto-generated method stub
//2,将字符串转换成字符数组
char[] ch=str.toCharArray();
//3,定义一个map集合,用来存储数据,由于有序,所以定义TreeMap
Map map=new TreeMap();//由于存入的数据为字符和int 所以泛型应为Character和Integer
//4,定义for循环,对数组的元素进行遍历
for (int i = 0; i < ch.length; i++) {
//扩展:当输入的字符串中含有其他字符时,应进行判断,此字符将不存入map中
Character key = ch[i];
if(!(key>='a'&&key<='z'||key>='A'&&key<='Z'))
{continue;}
int count=0;//定义计数器,用来记录字母出现的次数
//5,通过get()方法获取键值,并进行判断是否为空
Integer value=map.get(key);
if(!(value==null))
{
count=value;
}
count++;
map.put(key, count);

}
//System.out.println(map);用于验证是否成功

return toString(map);//要按指定的格式输出,定义一个方法来实现此功能,数据个数多
//,类型不一致,想到使用StringBuilder
}

public static String toString(Map map) {
// TODO Auto-generated method stub
StringBuilder str=new StringBuilder();
for (Map.Entry me : map.entrySet()) {
Character key=me.getKey();
Integer volue=me.getValue();
str.append(key+"("+volue+")");
}
return str.toString();
}

}
/*总结:当对象存在对应关系时,首先就要想到使用map集合来进行存储
* 利用建表法来解决,map集合有一个特性,键唯一,通过get()方法可以获得键值,且键值允许为空
*什么时候用StringBuilder?数据多,类型不同,结果返回字符串
* */

27,
package day20;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class Test3 {

/**
* @param args
* @throws ParseException
*/
public static void main(String[] args) throws ParseException {
// TODO Auto-generated method stub
//"2012/3/17","2012-5-28"问,间隔多少天?
/*
* 1,只有毫秒可以相减。
* 2,获取毫秒值,字符串-->日期对象-->毫秒值。
*/
//1,将字符串转换成日期对象
String str1="2012/8/17";//?为什么2012/3/17不行
String str2="2012@5@28";
long day = zhuanHuan(str1,str2);
System.out.println("间隔"+day+"天");
}

public static long zhuanHuan(String str1,String str2) throws ParseException {
char[] ch=str1.toCharArray();
char c=ch[4];
char[] ch1=str2.toCharArray();
char c1=ch1[4];
DateFormat df=new SimpleDateFormat("yyyyMMdd");
DateFormat df1=new SimpleDateFormat("yyyy"+c1+"MM"+c1+"dd");
Date date1=df.parse(str1);
Date date2=df1.parse(str2);
//2,将日期对象转换成毫秒值
long time1=date1.getTime();
long time2=date2.getTime();
long temp=Math.abs(time2-time1);
System.out.println(temp);
long day=temp/(24*60*60*1000);
return day;
}

}

二、IO流

C:\Users\xu\Documents\JavaSE0620\day23e\src\cn\itcast\test Test.java(配置文件的书写)
C:\Users\xu\Documents\JavaSE0620\day23e\src\cn\itcast\buffer MyBufferedReader.java(自定义缓冲区)
C:\Users\xu\Documents\JavaSE0620\day22e\src\day22 GetFilesTest.java(文件目录太深的解决方案)
C:\Users\xu\Documents\JavaSE0620\day22e\src\day22 Test3.java(获取目录中的.avi文件)
C:\Users\xu\Documents\JavaSE0620\day24e\src\cn\itcast\otherio\sequence\SequenceInputStreamDemo.java (演示序列流。SequenceInputStream)
C:\Users\xu\Documents\JavaSE0620\day24e\src\cn\itcast\splitfile(文件切割器,必须会)
按照字节数截取一个字符串。"abc你好"如果截取到半个中文,舍弃。比如 截取4

字节,abc。截取5个字节abc你。定义功能实现

三、String
1,子串在整串中出现的次数。"nbadfnbaghjnbaklnba"
E:\传智播客面试班--0620java基础班\课堂 ---------视频\day16e\src\cn\itcast\string\test\StringTest3.java
2,需求4:两个字符串的最大相同子串。"sadfcctvghjkl" "zxcctvcv"
E:\传智播客面试班--0620java基础班\课堂 ---------视频\day16e\src\cn\itcast\string\test\StringTest4.java
3,"23 10 -8 0 3 7 108"对字符串中的数值进行升序排序后,生成一个数值有序的字符串。 "-8 0 3 7 10 23 108"
E:\传智播客面试班--0620java基础班\课堂 ---------视频\day17e\src\cn\itcast\wrapper\Test.java
4,
四、网络编程
1, 通过UDP协议。 完成一个聊天程序。 群聊
C:\Users\xu\Documents\JavaSE0620\day26e\src\day26\CharTest_my.java
2,

五、异常大集合
ArrayIndexOutOfBoundsException:访问到了数组不存在的索引时,会发生该异常。
NullPointerException:当使用没有任何实体指向的引用变量操作实体时,运行会发生该异常。


























相关主题
文本预览
相关文档 最新文档