java面试宝典读记

    第一到第四章  

      每个人都有自己的观点和人生态度,每个人的性格才学也不一样,关于找工作,如果开始你就是顺利的你就用想着改变自己多去准备一些关于找工作的套路。但是不顺利的话就会想着怎么样怎样改变怀疑自己的能力。关于笔试和面试,其实对于笔试成绩不是特别得重要,在我们找工作的时候我的笔试成绩都是差不多的因为出牛逼的大牛外我们大部分都是有助攻的,除了大牛外这些笔试成绩最多可以用来当做你得到这些工资的依据(比别人少)。短短的面试不可能发现你这个人到底怎样因为你面试多了你习惯了面试的套路,所以面试官总是想试图发现你的人生观和对待事情的应对,也不排除第一印象好和不好,那结果就明了了。但是我想说两点。一是自信:切忌在工作室关于这一点还没怎么准备好之类的话(亲身经验,面试官建议我不要再说没准备好,在学中,学得不好之类的话),因为有些不如你的说的话把自己包装得很牛,所以还是在保持谦卑的情况下不要自傲就行。二是当你觉得自己可以尝试不同方向的工作时尽可能找准一个方向,当然可以去尝试,因为“吾生也有涯而知也无涯,以有涯随无涯殆己”。一个人精力是有限的留给你的时间也是有限的所以几头都抓的牛人还是很少的,所以能尽早确定一个方向的工作全力准备的胜算还是大于多方向尝试,但是提前海投还是必要的,普遍撒网重点捉鱼。

         无论工作定了与否专业知识还是要强的,你不是为了找到工作还要以后工作,所以还是要自身素质过硬才扛得起以后的生活。

第五章 java基本概念

java类加载器:

类的加载过程 :JVM将类加载过程分为三个步骤:装载(Load),链接(Link)和初始化(Initialize)链接又分为三个步骤。1) 装载:查找并加载类的二进制数据;
2)链接:验证:确保被加载类的正确性;准备:为类的静态变量分配内存,并将其初始化为默认值;解析:把类中的符号引用转换为直接引用;3)初始化:为类的静态变量赋予正确的初始值。类的加载指的是将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个这个类的Java.lang.Class对象,用来封装类在方法区类的对象。类的加载是具有层次机构父类委托机制包括:

1)Bootstrap ClassLoader(启动类加载器)负责加载$JAVA_HOME中jre/lib/rt.jar里所有的class,由C++实现,不是ClassLoader子类。
2)Extension ClassLoader(标准类加载器)负责加载java平台中扩展功能的一些jar包,包括$JAVA_HOME中jre/lib/*.jar或-Djava.ext.dirs指定目录下的jar包。
3)App ClassLoader(系统类加载器)负责记载classpath中指定的jar包及目录中class
4)Custom ClassLoader属于应用程序根据自身需要自定义的ClassLoader,如tomcat、jboss都会根据j2ee规范自行实现ClassLoader加载过程中会先检查类是否被已加载,检查顺序是自底向上,从Custom ClassLoader到BootStrap ClassLoader逐层检查,只要某个classloader已加载就视为已加载此类,保证此类只所有ClassLoader加载一次。而加载的顺序是自顶向下,也就是由上层来逐层尝试加载此类。

jiava编码/自增/类型转换

java的java使用的编码字符是Unicode,涉及到面向字节和面向字符的编码,涉及到字符编码的转换,java的字符占两个字节可以表示一个汉字。

自增操作:关于先赋值和先运算的规则考察。++在前和在后的不同,一个先自加一个先赋值。

类型转换:书中例子提到不同类型的转换,转换涉及到自动转换和强制类型转换,数据类型四类八种,不参与自动转换的byte、short、char三种。(例子中讲到length属性和length()方法的不同)。java的六种包装类Boolean、Character、Integer、Long、Float和Double。String和Date本身是类。利用包装类的各种方法进行转换。

运算符的等级:

1级2级3级4级5级6级7级8级9级10级11级12级13级14级15级16级
.()++ --new* / %+ -》《 >>< >= >=== !=&^!&&||?:= += -=&= <<= 

 && 与&,||与|区别。前者短路或者不短路。关于三元运算中,当两个表达式有一个常量表达式另一个是T,而常量表达式可以被T表示输出是T类型。移位操作参数先进性模32运算,并且是对二进制操作,二进制操作8是一个循环n>>32等于n>>0,n>>33相当于n>>1。

异常:

运行时异常是一个超类当java虚拟机正常时一定会跑出Thorwable类所有异常和错误的超类,有两个子类Error和Exception,分别表示错误和异常。其中异常类Exception又分为运行时异常(RuntimeException)和非运行时异常, 这两种异常有很大的区别,也称之为不检查异常(Unchecked Exception)和检查异常(Checked Exception)。异常的体系结构

 异常处理:

异常是程序遇到非正常的情况或者意外行为,一般引发异常有代码或调用代码有误,操作系统资源不可用,除数为零、下标越界等。关于异常处理的关键字try、catch、throw、throws、finally。关于try、catch、finally三个语句块均不能单独使用,三者可以组成 try...catch...finally、try...catch、 1)try...finally三种结构,catch语句可以有一个或多个,finally语句最多一个。 2)、try、catch、finally三个代码块中变量的作用域为代码块内部,分别独立而不能相互访问。如果要在三个块中都可以访问,则需要将变量定义到这些块的外面。3)多个catch块时候,只会匹配其中一个异常类并执行catch块代码,而不会再执行别的catch块, 并且匹配catch语句的顺序是由上到下。

 throw、throws关键字 throw关键字是用于方法体内部,用来抛出一个Throwable类型的异常。如果抛出了检查异常, 
则还应该在方法头部声明方法可能抛出的异常类型。该方法的调用者也必须检查处理抛出的异常。 如果所有方法都层层上抛获取的异常,最终JVM会进行处理,处理也很简单,就是打印异常消息和堆栈信息。如果抛出的是Error或RuntimeException,则该方法的调用者可选择处理该异常。

异常处理的一般原则

1、能处理就早处理,抛出不去还不能处理的就想法消化掉或者转换为RuntimeException处理。 因为对于一个应用系统来说,抛出大量异常是有问题的,应该从程序开发角度尽可能的控制异常发生的可能。 
2、对于检查异常,如果不能行之有效的处理,还不如转换为RuntimeException抛出。这样也让上层的代码有选择的余地――可处理也可不处理。3、对于一个应用系统来说,应该有自己的一套异常处理框架,这样当异常发生时,也能得到统一的处理风格, 将优雅的异常信息反馈给用户。

final、finally、finalize

A: final可以控制成员、方法、或者是一个类是否可被覆写或者继承等功能。1)final修饰成员即被初始化便不可改变,不可改变说的是其基本类型值不可,对于对象来说而其引用不可变。2)final修饰方法不可复写(用以内嵌)。3)final修饰类,此类不可以被继承。不能与abstract共存。

B:finally:是对java异常的补充,finally代码总会执行不管异常是否发生。使用finally可以维护对象内部状态,并可以清理内存资源。try{}里有一个return语句,那紧跟后的finally{}里的code会在return前执行。

C:finalize:这个是用来控制java中不易控制并且非常重要的资源例如一些I/O操作,数据的链接。

反射:反射是指程序可以访问、检测和修改它本身的状态或行为的一种能力。http://www.cnblogs.com/lzq198754/p/5780331.html

                                  第六章、传值和引用

    不管java参数的类型是什么,一律传递参数的副本,

例1:基本类型引用传递

public class test {
public static void main(String[] args) {
	boolean test=true;
	System.out.println(test);
	test(test);
	System.out.println(test);
}
public static void test(boolean test){
	test=!test;
	System.out.println(test);
}
}

结果true  false  true。以参数形式传递简单类型变量时实际上将参数的值作为副本传递给方法函数那么不管函数中怎么改变其结果对源值

例二。对象引用传递

public class test {
public static void main(String[] args) {
	StringBuffer string=new StringBuffer("hello");
	test(string);
	System.out.println(string);
}
public static void test(StringBuffer str){
	str.append(",world");
}
}

结果输出hello,world。传入的string是一个引用引用变量传递对象形式的变量时实际是引用的一个副本即是对象的地址,通过地址找到值修改对象。

例3、string类型的引用

public class test {
public static void main(String[] args) {
	String string="hello";
	test(string);
	System.out.println(string);
}
public static void test(String str){
	str="world";
}
}

结果输出hello。String类是final型,不可修改,相当于从新分配一块地址进行操作那么跟原来的就没有关系了也就不会影响源变量.

静态变量和私有变量:例题中告诉我们,变量被定义为私有并不能阻止构造器对其进行初始化。静态变量的布尔类型默认值是false。静态方法不能访问非静态变量。

输入输出流:InputStream/OutputStream(字节操作):抽象类,基于字节的输入/输出操作。Reader/Writer(字符操作):抽象类,基于字符的输入/输出操作。OutputStreamWriter/InputStreamReader(字节、字符转换类):分别是Writer/ Reader的子类,需要InputStream/OutputStream类对象做参数。

序列化:Java 串行化技术可以使你将一个对象的状态写入一个Byte 流里,并且可以从其它地方把该Byte 流里的数据读出来,重新构造一个相同的对象。这种机制允许你将对象通过网络进行传播,并可以随时把对象持久化到数据库、文件等系统里。Java的串行化机制是RMI、EJB等技术的技术基础。将需要被序列化的类实现Serializable接口,然后使用一个输出流(如:FileOutputStream)来构造一个ObjectOutputStream(对象流)对象,接着使用ObjectOutputStream对象的writeObject(Objectobj)方法就可以将参数为obj的对象写出(即保存其状态),要恢复的话则用输入流。
        用途:利用对象的串行化实现保存应用程序的当前工作状态,下次再启动的时候将自动地恢复到上次执行的状态。序列化是将java对象内存中的数据变成一串二进制数据,然后把这些数据存放在持久数据存储设备上,当需要还原这些数据的时候,再通过反序列化的过程把对象还原到内存中。
Serializable接口没有任何需要实现的抽象方法,仅仅告诉JVM对象实例可以进行序列化,并通过序列ID标识,它由静态的serialVersionUID变量提供。

第七章、循环、条件、概率

递归的使用是一个解决问题思路,但效率不高他是一个循环往复的过程。

递归列举数组中字符组合种类

public class test {
public static void main(String[] args) {
	String []a=new String[]{
			"1","2","3","4"
	};
	listAll(Arrays.asList(a),"");
}
private static void listAll(List<String> asList, String string) {
	// TODO Auto-generated method stub
	System.out.println(string);
	for(int i=0;i<asList.size();i++){
		List temp=new LinkedList<>(asList);
		listAll(temp, string+temp.remove(i));
	}
}
}

例2求一个字符串重复出现次数最多的字符。

public class test {
public static void main(String[] args) {
	        String data="ddaabbbcccc";  
	        getMax(data);  
	    }  
	    private static void getMax(String data) {  
	        //将字符串使用toCharArray()方法变为字符数组,再遍历数组分别存入ArrayList和TreeSet  
	        List<String> list = new ArrayList<String>();  
	        Set<String> set = new TreeSet<String>();  
	        char[] array = data.toCharArray();  
	        for (int i = 0; i < array.length; i++) {  
	            list.add(String.valueOf(array[i]));  
	            set.add(String.valueOf(array[i]));  
	        }  
	        //利用集合工具类Collections的sort()方法对ArrayList排序  
	        Collections.sort(list);  
	        //使用StringBuffer存放list,并用toString()方法转换为字符串。  
	        StringBuffer sb = new StringBuffer();  
	        Iterator<String> iterator = list.iterator();  
	        while(iterator.hasNext()){  
	            sb.append(iterator.next());  
	        }  
	        String string = sb.toString();  
	        //至此将字符串变为了有序不允许重复的set和有序且字母有重复的String  
	        //迭代set,使用indexOf和lastIndexOf方法操作String得到重复字母次数  
	        //max记录最大重复次数,maxString记录当前最大字符串,maxList存储所有最大字符,maxList.size()即为重复字符个数  
	        int max=0;  
	        String maxString="";  
	        ArrayList<String> maxList = new ArrayList<String>();  
	        for(Iterator<String> it = set.iterator();it.hasNext();){  
	            String s = (String) it.next();  
	            int begin = string.indexOf(s);  
	            int end = string.lastIndexOf(s);  
	            int value = end-begin+1;  
	            if(value>max&&value>1){  
	                maxList.clear();//产生新的最大字符要清空之前的最大字符,否则输出最大字符不正确。  
	                max = value;  
	                maxString = s;  
	                maxList.add(s);  
	            }else if(value==max){  
	                maxList.add(s);  
	            }  
	        }  
	        System.out.println(list);  
	        System.out.println(set);  
	        for (int i = 0; i < maxList.size(); i++) {  
	            System.out.println("最大字符"+maxList.get(i));  
	        }  
	        System.out.println("最多次数:"+max);  
	    }  
	}

第8章、java内存管理。

垃圾收集

java语言的优势不要求程序员显示的分配内存和释放内存。,一个程序可以建议垃圾回收器回收但是不能强迫执行,当一个对象的所有引用被置空时这个对象就可以被垃圾回收器回收。java垃圾回收机制,是指jvm用于释放那些不在使用的对象所占的空间。(1)不要试图假定垃圾回收发生的时间一切都是未知。(2)java提供一些和垃圾回收器打交道的方法调用System.gc(),但同样是一个不确定的方法。有了垃圾回收机制也不一定完全避免内存泄漏。

Java的内存管理在java中程序员通过关键字new创建对象,在堆中分配内存,对象的释放是由GC决定和执行的程序分配内存,GC回收,jvm就要监视每个对象的申请、引用、被引用、赋值等。

内存泄漏:

        是指分配的一些对象,这些对象存在两个特点:1)对象是可达的在有向图中存在通路与其连接,2)对象是无用的即程序以后不再使用这些对象。因此忘记释放先前分配的内存就会造成内存泄漏,典型的内存泄漏及其原因。

(1)全局集合:全局的数据存储,必须使用某种机制清楚不再需要的数据,一种是执行周期性清楚任务,一种是使用反向链接计,然后集合负责统计集合中每个入口的反向链接数目,当反向链接数目为零时该元素就该从集合中移除了。

(2)缓存:缓存是一种数据结构,用于快速查找已经执行的操作结果。这是一种潜在的破坏性设计,因此对其设计进行修改步骤变为,A;检查结果在缓存中是否有,有就返回。B:没有就计算。C:如果缓存占空间太大就移除存入最近的结果。D结果存入缓存。

(3)ClassLoader:classload结构的复杂想对于内存泄漏存在很大威胁,因为它不仅涉及到常规对象的引用还涉及到元对象的引用,比如字段、方法和类。只要有对元字段的引用ClassLoad就会驻留在JVM中。内存泄漏的信号是OutOfMemoryError。有可能是因为你的程序和生产系统不完全相同,也有可能程序确实需要更多的内存。
4)Clone:Object类的clone方法是一个protect的不能直接调用,可以被子类调用。object的clone知道对象的大小会为对象分配足够的空间。并将旧的对象分配到新的对象中,但object。clone()执行之前必须先检查class是否实现了cloneable接口。java中clone的含义。假设x是一个非空对象则,x.clone()!=x为true他们是同一个对象。x.clone().getClass()==x.getClass()为true他们为同一类。x.equals(x.clone())为true说明逻辑上应该相当。clone方法为object中定义的而且是protect类型的只有实现了这个接口。才能在该类实例上调用clone方法。

 

第9章

类是描述一组有相同特征(属性)和相同行为(方法)的对象。对象与实例,实例是从对象模型中抽出的产品。不用实例化的:静态方法为类所共有也就是这个方法是属于所有类的对象使用。要实例化的:具体到某个点不是面向公众的就要实例化。(例1 99页定义对象必须在声明时定义)

object的公共方法

clone方法保护方法,实现对象的浅复制,只有实现了Cloneable接口才可以调用该方法,否则CloneNotSupportedException异常。
getClass方法final方法,获得运行时类型。
toString方法该方法用得比较多,一般子类都有覆盖。
finalize方法该方法用于释放资源。因为无法确定该方法什么时候被调用,很少使用。
equals方法该方法是非常重要的一个方法。一般equals和==是不一样的,但是在Object中两者是一样的。子类一般都要重写这个方法。
hashCode方法该方法用于哈希查找,重写了equals方法一般都要重写hashCode方法。这个方法在一些具有哈希功能的Collection中用到。一般必须满足obj1.equals(obj2)==true。可以推出obj1.hash-Code()==obj2.hashCode(),但是hashCode相等不一定就满足equals。不过为了提高效率,应该尽量使上面两个条件接近等价。
wait方法wait方法就是使当前线程等待该对象的锁,当前线程必须是该对象的拥有者,也就是具有该对象的锁。wait()方法一直等待,直到获得锁或者被中断。wait(longtimeout)设定一个超时间隔,如果在规定时间内没有获得锁就返回。调用该方法后当前线程进入睡眠状态,直到以下事件发生。
(1)其他线程调用了该对象的notify方法。
(2)其他线程调用了该对象的notifyAll方法。
(3)其他线程调用了interrupt中断该线程。
(4)时间间隔到了。
此时该线程就可以被调度了,如果是被中断的话就抛出一个InterruptedException异常。
notify方法该方法唤醒在该对象上等待的某个线程。
notifyAll方法该方法唤醒在该对象上等待的所有线程。
java创建对象的几种方式:1)用new语句创建对象。2)运用反射手段调用java.lang.Class或者java.lang.reflect.Constructor类的newInstance()实例方法。4)运用反序列化手段调用java.io.ObjectInputStream对象的readObject()方法。

HashMap与Hashtable的区别:都是Map的接口实现将唯一键映射到特定值之上。HashMap类没有分类或者排序允许一个null建和多个null值。Hashtable不允许null键与null值比hashmap慢因为他是同步的。Hashtable继承自Dictionary类HashMap是java1.2引进的Map interface的一个实现。HashMap把Hashtable的contains方法去掉,改为containsvalue。

                                    第10章、继承与接口


1、接口:

广义的接口:凡是为一个类提供给外部使用的部分都可以被称为接口,广义接口真正的意义在于继承中体现多态的功能。狭义接口是指特定的函数集合一般用interface声明,他表示一个方法集合。

2、成员函数重载:

(1)相同的范围(同一类中)(2)函数名字相同。(3)参数不同。覆盖:(1)不同范围(派生类与基类)(2)函数名字相同(3)参数相同。

3、继承:

是一种通过扩展一个已有的对象的额实现,从而获得新功能的复用方法。泛化类可以显示的捕捉那些公共的属性和方法,特殊类的则通过附加属性和方法进行实现扩展。继承会破坏封装性,因为会将父类的实现细节暴露给子类。继承本质上属于白盒式代码复用。(组合:黑盒式代码复用)

class A{
	public void printValue(){
		System.out.println("classA");
	}
}
 class B extends A{
public void printValue(){
	System.out.println("classB");
}	
}
public class test {
public static void main(String[] args) {
	B b=new B();
	b.printValue();//classB
	A a=(A)b;
	a.printValue();//classB孔子装爹但还是孔子,所以只能调用孔子的方法。
	 A a1=new A();
	 a1.printValue();//classA
	}  
}

如果是静态方法就不一样了

class A{
	public static void printValue(){
		System.out.println("classA");
	}
}
 class B extends A{
public static void printValue(){
	System.out.println("classB");
}	
}
public class test {
public static void main(String[] args) {
	B b=new B();
	b.printValue();
	 A a1=new B();
	 a1.printValue();
	}  
}

结果是classB,classA。静态方法内存中地址固定,两个方法占用不同的空间具体执行哪一个看那个类调用。

4、super:

子类的构造函数如果要引用super必须要把super放在函数的首部。为什么?子类是从父类继承而来,继承了父类的属性和方法,如果在子类中先不完成父类的成员的初始化,则子类无法使用,应为在java中不允许调用没初始化的成员。在构造器中是顺序执行的,也就是说必须在第一行进行父类的初始化。而super能直接完成这个功能。子类会掩盖掉父类的同名方法或者变量如果想使用就用super关键字。

5、this关键字:

使用在一个函数成员的内部指向当前对象,
 

class test {
	int var;
	test(double var){
		this.var=(int )var;
	}
	test(int var){
		this("hello");
	}
	test(String s){
		this();
		System.out.println(s);
	}
	test(){
		System.out.println("word");
	}
public static void main(String[] args) {
	test t=new test(5);
	}  
}

输出word hello。

6、抽象类与接口:

抽象类:1)只能当做其他类的基类不能直接被实例化对抽象类不能使用new操作符。2)抽象类允许包含抽象成员但不是必须的。可以有非抽象方法。3)抽象类不能同时是final。4)如果一个类继承抽象类则必须通过覆盖实现所有继承而来的抽象成员。5)抽象类可以被抽象类继承结果仍是抽象类。6)抽象类容易被声明。

7、java集合类继承关系:


8、java接口:

1)接口用于描述对外提供的公共服务,因此接口中的成员常量和方法必须是共开的确保外部使用访问他们。2)接口仅仅描述系统能做什么不指明如何做所以接口中方法都是抽象的。3)接口不涉及和具体实现相关的细节,因此接口没有构造方法不能被实例化,没有实例变量,只有静态常量。4)接口中实现类是所有实现类共有的既然共有肯定是不变的东西所以变量是不可变类型也就是常量。5)接口中不可以定义变量。如果定义变量接口的方法又是抽象的,即没有方法可以修改这些属性。

通俗讲你认为变化的东西就放在自己的实现中不能放在接口中去,接口只是对一类事物的更高层次的抽象对修改关闭对扩展开放,接口是对开闭原则的一种体现。所以接口方法默认是public abstract;接口中不可定义变量只可以定义常量缩衣节口默认的修饰符是public static final常量,且必须赋初值。

                                     数据结构/计算机网络

1、存储结构:

1)随机存取:可以随意直接存取任意一个元素,如内存可以通过地址直接访问任意一个空间。2)顺序存取:从前往后逐个访问像链表结构。3)索引存取:是为某个关键字建立索引表。4)散列存储:建立散列表相当于一种索引。链式存储是顺序存储。

2、面试题:

面试题1:

有1千万个有重复的短信,以文本的形式保存,一条一行也有重复。请5分钟内中出重复最多的10条短信。

1)哈希表的方法:分若干组,进行边扫描边建立散列表。2)采用从小到大排序的办法。(可以从单个字搜索比较,找出重复的top10,然后两个字以此类推。对于字数多的除了hash算法,可以选择只抽取头。中和尾部进行粗判加快查找还要做以标记,从各组备选的top10比较得出结果)。3)采用内存映射。

面试题2:

有20个数组,每个数组有500个元素,并且是有序排列好的,现在在这20*500个数中找出排名前500的数
(从数组末端起始)从20个数组中各取一个数,并记录每个数的来源数组,建立一个含20个元素的大根堆。此时堆顶就是最大的数,取出堆顶元素,并从堆顶元素的来源数组中取下一个数加入堆,再取最大值,一直这样进行500次即可。复杂度500xlog(20)。

面试题3:

辗转相除法时间复杂度:欧几里德算法基于数论等式gcd(a,b)=gcd(b,a mod b)其时间复杂度O(longn)

==与equals:

class test {
public static void main(String[] args) {
	String s1="abc";
	String s2=s1;
	String s5="abc";
	String s3=new String("abc");
	String s4=new String("abc");
	System.out.println(s1==s5);//true
	System.out.println(s1==s2);//true
	System.out.println(s1.equals(s2));//true
	System.out.println(s3==s4);//false
	System.out.println(s1.equals(s4));//true
	System.out.println(s3.equals(s4));//true
	}  
}

==判断两个变量是否指向同一个地址,equals判断两个object是否一样(String字符串“abc”放在常量池)

面试题4

写一个函数,在给定的整数数组中找出支配者是多少,如果一个数组中没有支配者,“支配着” 是在数组中出现频率超过一半的整数,例如{3, 2, 3, 3, 0, 2, 3, 4, 3},其中3出现5次,5除以9大于0.5,所以3是支配者。

public class Data{   
    public static void main(String[] args) {  
        int[] ints = {3, 2, 3, 3, 0, 2, 3, 4, 3};  
        int j = judge(ints);       
        if(j == -1){  
            System.out.println("No dominator");  
        }else{  
            System.out.println("The dominator is : " + ints[j]);  
        }  
    }  
    private static int judge(int[] ints) {  
        Arrays.sort(ints);  
        int counter = 1;  
        for(int i=0; i< (ints.length-1); i++){  
            if(ints[i] == ints[i+1]){  
                counter++;  
                if((((double)counter) / ints.length) > 0.5){  
                    return i ;  
                }  
            }else{  
                counter = 1;  
            }            
        }  
        return -1;  
    }  
}  

 约瑟环问题

30个人十五个教徒,十五个非教徒,站成环数到九离开。

class test {
public static void main(String[] args) {
	boolean[] use=new boolean[30];
	for(int i=0;i<use.length;i++)
	{
		use[i]=true;
	}
	int left=use.length;
	int countnum=0;
	int index=0;
	while(left>1){
		countnum++;
		if(countnum==9){
			countnum=0;
			use[index]=false;
			left--;
		}
		index++;
		if(index==use.length)
			index=0;
	}
	for(int i=0;i<use.length;i++)
	{
		System.out.println(i+"="+use[i]+" ");}
	}  
}

 单例模式

public class SingletonTest {  
    private SingletonTest() {  
    }  
    private static final SingletonTest instance = new SingletonTest();  
    public static SingletonTest getInstancei() {  
        return instance;  
    }  
    //饱汉式
    // 定义一个SingletonTest类型的变量(不初始化,注意这里没有使用final关键字)
    /*private static SingletonTest instance=null;   
    public static SingletonTest getInstance() {   
        if (instance == null)   
            instance = new SingletonTest();   
        return instance;   
    }  */
} 
}

简述Struts下的模式

MVC模式(Model、View、controller)在MVC模式中,一个应用被划分成了模型(Model)、视图(View)和控制器(Controller)三个部分。模型是应用程序的主体部分,模型表示业务数据或者业务逻辑,视图是应用程序相关的部分是用户看到并与之交互的界面,控制器就是根据用户的输入控制用户界面数据显示和更新的model对象状态,mvc实现功能和显示的分离,同时提高了应用系统的可谓护性、可扩展性、可移植性和组件的可服用性。                                                       

                                数据库/计算机网络

1、执行数据库查询时,如果要查询的数据有很多,假设有1000万条,用什么办法可以提高查询速率?在数据库方面或java代码方面有什么优化的方法。

1)在数据库设计方面:(1)建立索引;(2)分区(MySQL,比如按时间分区);(3)尽量使用固定长度的字段;(4)限制字段长度;
2)在数据库I/O方面:(1)增加缓冲区;(2)如果涉及表的级联,不同的表存储在不同的磁盘上,以增加I/O速度;
3)在SQL语句方面:(1)优化SQL语句,减少比较次数;(2)限制返回的条目数(MySQL中用limit);
4)在Java方面:如果是反复使用的查询,使用PrepaerdStatement减少查询次数。

2、Ip地址:A类地址是有1B的网络地址和3B的主机地址,网络地址的最高位是0,第一个字段取值1-127,A类可连接16387064台主机,internet有126个A类地址。B类地址2B的网络地址网络号最高位10,第一字段128-191,可连接64516台主机网络号16256个B类地址。C类3B网络号,首三位110第一字段192-223。可连接254台主机,网络号2054512个网络号,D类多点传播第一字节1110,第一字节224-239。全为0的地址为当前主机全为机的地址为当前子网的广播地址。E类以11110开始第一字段240-254。子网掩码(subnet mask)又叫网络掩码、地址掩码。子网掩码不能单独存在,它必须结合IP地址一起使用。子网掩码只有一个作用,就是将某个IP地址划分成网络地址和主机地址两部分。

J2EE

Spring的特点?为什么要用Spring?Spring通过一种称作控制反转(IoC)的技术促进了松耦 合。当应用了IoC,一个对象依赖的其它对象会通过被动的方式传递进来,而不是这个对象自己创建或者查找依赖对象。你可以认为IoC与JNDI相反——不 是对象从容器中查找依赖,而是容器在对象初始化时不等对象请求就主动将依赖传递给它。

1.使用Spring的IOC容器,将对象之间的依赖关系交给Spring,降低组件之间的耦合性,让我们更专注于应用逻辑
2.可以提供众多服务,事务管理,WS等。
3.AOP的很好支持,方便面向切面编程。
4.对主流的框架提供了很好的集成支持,如hibernate,Struts2,JPA等
5.Spring DI机制降低了业务对象替换的复杂性。
6.Spring属于低侵入,代码污染极低。
7.Spring的高度可开放性,并不强制依赖于Spring,开发者可以自由选择Spring部分或全部。

Hibernate工作原理及为什么要用?1)读取并解析配置文件。2)读取并解析映射信息,创建SessionFactory。3)打开Sesssion。4)创建事务Transation。5)持久化操作。6)提交事务。7)关闭Session。8)关闭SesstionFactory

为什么用:1)对JDBC访问数据库的代码做了封装,大大简化了数据访问层繁琐的重复性代码。2)hibernate是一个基于JDBC的主流持久化框架,是一个优秀的ORM实现。他很大程度的简化DAO层的编码工作。3)hibernate使用Java反射机制,而不是字节码增强程序来实现透明性。4)hibernate的性能非常好,因为它是个轻量级框架。映射的灵活性很出色。它支持各种关系数据库,从一对一到多对多的各种复杂关系。

说一下线程和进程

计算机的核心是CPU,它承担了所有的计算任务。它就像一座工厂时刻在运行。假定工厂的电力有限,一次只能供给一个车间使用。也就是说一个车间开工的时候,其他车间都必须停工。背后的含义就是,单个CPU一次只能运行一个任务。进程就好比工厂的车间,它代表CPU所能处理的单个任务。任一时刻CPU总是运行一个进程,其他进程处于非运行状态。一个车间里可以有很多工人,他们协同完成一个任务。线程就好比车间里的工人,一个进程可以包括多个线程。车间的空间是工人们共享的,比如许多房间是每个工人都可以进出的。这象征一个进程的内存空间是共享的,每个线程都可以使用这些共享内存。可是每间房间的大小不同,有些房间最多只能容纳一个人,比如厕所里面有人的时候,其他人就不能进去了,这代表一个线程使用某些共享内存时其他线程必须等它结束,才能使用这一块内存。一个防止他人进入的简单方法,就是门口加一把锁。先到的人锁上门,后到的人看到上锁就在门口排队,等锁打开再进去。这就叫互斥锁(Mutual exclusion,缩写 Mutex),防止多个线程同时读写某一块内存区域。还有些房间,可以同时容纳n个人,比如厨房。也就是说如果人数大于n,多出来的人只能在外面等着。这好比某些内存区域,只能供给固定数目的线程使用。这时的解决方法就是在门口挂n把钥匙。进去的人就取一把钥匙,出来时再把钥匙挂回原处,后到的人发现钥匙架空了,就知道必须在门口排队等着了。这种做法叫做信号量(Semaphore),用来保证多个线程不会互相冲突。mutex是semaphore的一种特殊情况(n=1时)。也就是说,完全可以用后者替代前者。但是,因为mutex较为简单,且效率高,所以在必须保证资源独占的情况下,还是采用这种设计。

操作系统的设计,因此可以归结为三点:

(1)以多进程形式,允许多个任务同时运行;

(2)以多线程形式,允许单个任务分成不同的部分运行;

(3)提供协调机制,一方面防止进程之间和线程之间产生冲突,另一方面允许进程之间和线程之间共享资源。

操作系统

1、多用户:容许同一时间有很多人使用同一部机器,多任务:为了使很多程序可以一同执行,这个特点叫做多任务。多任务又分协同式和抢占式。

2、只有具备执行权限才允许用户进入一个文件的系统的目录。

3、所有的32位应用程序都有4GB的进程地址空间,因为32位地址最多可以映射4GB的内存。对于Windows,应用程序可以访问2GB的进程地址空间(32位Linux可以访问3GB地址空间),这就是称为用户模式的虚拟地址空间。这 2GB的用户模式虚拟地址空间位于4GB地址空间的低一半,而与之相对应的高一半2GB地址空间由操作系统内核使用,因此被成为内核模式的虚拟地址空间。在一个进程中,所有的线程读共享相同的2GB用户模式虚拟地址空间。为了缓解地址空间的不足,微软提供了一个权宜的解决方案,所有从Windows 2000 Server开始的操作系统版本都提供了一个boot.ini启动开关(/3GB),可以为应用程序提供访问3GB的进程地址空间的能力,从而将内核模式的地址空间限定为1GB。

4、sleep()与wait()的区别。属于thread类sleep()线程停止一段时间的方法,在休止一段时间期满后不一定会立即执行,因为那一时刻其他线程可能正在运行,而且没有被放弃调度执行,除非醒来的线程具有更高的优先级,或者正在运行的线程被其他线程阻塞。wait(),在线程交互时,如果线程对一个同步对象x发出一个wait()调用,该线程会暂停执行,被调用线程会进入等待状态,知道被唤醒或等待时间到它是object类里的。

5、win32环境中,线程的3中基本模式,单线程、单元线程、自由线程。

单线程:简单的应用程很可能是单线程应用程序,仅包含与应用程序对应的线程,进程可以被定义为应用程序的实例。拥有该程序的内存空间大多数windows应用程序是单线程的即一个线程可以完成的操作。

单元线程:单元线程是一种稍微复杂的线程模式。标记用于单元线程的代码可以在其自己的线程中执行,并限制在自己的单元中。线程可以被定义为进程所拥有的实体。处理时将调度该进程。在单元线程模式中,所有线程都在主应用程序内存中各自的子段范围内运行。此模式允许多个代码实例同时但独立地运行。例如,在 .NET 之前,Visual Basic 仅限于创建单元线程组件和应用程序。

自由线程:多个线程可以同时调用相同的方法和组件与单线程不同自由线程不会限制在独立的内存空间。
 

public static void main(String args[]) {
   Thread t = new Thread() {
            public void run() {
                pong();
            }
        };
        t.run();
        System.out.print("ping");
    }
    static void pong() {
        System.out.print("pong");
    }

结果pongping。系统调用start方法才会启动一个新线程,进而调用run方法,单独调用run方法和普通方法一样。

6、java串行化:

对象的寿命通常随着生成该对象的程序的终止而终止。有时候,可能需要将对象的状态保存下来,在需要时再将对象恢复。我们把对象的这种能记录自己的状态以便将来再生的能力,叫作对象的持续性(persistence)。对象通过写出描述自己状态的数值来记录自己 ,这个过程叫对象的串行化(Serialization) 。串行化的主要任务是写出对象实例变量的数值。如果变量是另一对象的引用,则引用的对象也要串行化。这个过程是递归的,串行化可能要涉及一个复杂树结构的单行化,包括原有对象、对象的对象、对象的对象的对象等等。对象所有权的层次结构称为图表(graph)。

串行化的目的
Java对象的串行化的目标是为Java的运行环境提供一组特性,如下所示:
1) 尽量保持对象串行化的简单扼要 ,但要提供一种途径使其可根据开发者的要求进行扩展或定制。
2) 串行化机制应严格遵守Java的对象模型 。对象的串行化状态中应该存有所有的关于种类的安全特性的信息。
3) 对象的串行化机制应支持Java的对象持续性。
4) 对象的串行化机制应有足够的 可扩展能力以支持对象的远程方法调用(RMI)。
5) 对象串行化应允许对象定义自身的格式即其自身的数据流表示形式,可外部化接口来完成这项功能。

串行化方法
从JDK1.1开始,Java语言提供了对象串行化机制 ,在java.io包中,接口Serialization用来作为实现对象串行化的工具 ,只有实现了Serialization的类的对象才可以被串行化。Serializable接口中没有任何的方法。当一个类声明要实现Serializable接口时,只是表明该类参加串行化协议,而不需要实现任何特殊的方法。下面我们通过实例介绍如何对对象进行串行化。

串行化的注意事项
1.串行化能保存的元素
串行化只能保存对象的非静态成员交量,不能保存任何的成员方法和静态的成员变量,而且串行化保存的只是变量的值,对于变量的任何修饰符都不能保存。
2.transient关键字
对于某些类型的对象,其状态是瞬时的,这样的对象是无法保存其状态的。例如一个Thread对象或一个FileInputStream对象 ,对于这些字段,我们必须用transient关键字标明,否则编译器将报措。
另外 ,串行化可能涉及将对象存放到磁盘上或在网络上发达数据,这时候就会产生安全问题。因为数据位于Java运行环境之外,不在Java安全机制的控制之中。对于这些需要保密的字段,不应保存在永久介质中 ,或者不应简单地不加处理地保存下来 ,为了保证安全性。应该在这些字段前加上transient关键字。

7、java中的synchronized关键字

由于同一进程的多个线程共享同一片存储空间,在带来方便的同时,也带来了访问冲突这个严重的问题。Java语言提供了专门机制以解决这种冲突,有效避免了同一个数据对象被多个线程同时访问。

1)synchronized关键字可以作为函数的修饰符,也可作为函数内的语句,也就是平时说的同步方法和同步语句块。如果 再细的分类,synchronized可作用于instance变量、object reference(对象引用)、static函数和class literals(类名称字面常量)身上。
2)无论synchronized关键字加在方法上还是对象上,它取得的锁都是对象,而不是把一段代码或函数当作锁――而且同步方法很可能还会被其他线程的对象访问。
3)每个对象只有一个锁(lock)与之相关联。
4)实现同步是要很大的系统开销作为代价的,甚至可能造成死锁,所以尽量避免无谓的同步控制。

synchronized作用于某个对象实例内,某个类内。它可作用于方法和对象。

8、线程分为守护线程和非守护线程(用户线程),只有当JVM实例中尚存在任何非守护线程没有结束,守护线程就全部工作,只有当最后一个非守护线程结束守护线程随着JVM一同结束守护线程最典型的就是GC。

点击打开链接

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值