面试题杂记

来源:互联网 发布:centos 安装 tomcat 编辑:程序博客网 时间:2024/06/06 07:30

1. 进制之间的转换

// 十进制转化为十六进制,结果为C8。    Integer.toHexString(200);// 十六进制转化为十进制,结果140。Integer.parseInt("8C",16);//十进制转二进制Integer.toBinaryString(int i);

2.质数的定义

只有1和它本身两个因数的自然数

3.关键字null

null是一种特殊的值,可以将其赋给任何引用类型,也可以转化成任何类型。但不可以赋给变量类型,不可以赋给基本类型,如int,boolean等。

3.关于String

//String转成String[]String[] a = s.split(" ");//按空格划分//这里注意按小数点.划分的时候不能直接写.,应该写成//.String[] a = s.split("\\.");//将char转成String,String.valueOf()可以也可以将int转成String类型String s = String.valueOf('c');//数组不能直接通过toString的方式转成字符串String,必须通过  StringBuffer,或者Arrays.toString(arr)才能转成字符串,否则直接用arr.toString()得到的是hasnCode!!String[] str = {"abc", "bcd", "def"};StringBuffer sb = new StringBuffer();for(int i = 0; i < str.length; i++){ sb. append(str[i]);}String s = sb.toString();String s2 = Arrays.toString(str);//数组转ListString[] arr = new String[] {"str1", "str2"};  //这里特别注意,通过Arrays.asList(数组)的方式创建的List是AbstractList,不支持增删改查,如果希望能增删改,必须 new 一个LinkedList 或ArrayList!!List<String> list = Arrays.asList(arr); //如果是直接想新建一个List对象,则如下List list = new ArrayList(); //List转数组List<String> list = new ArrayList<String>();  list.add("str1");  list.add("str2");  int size = list.size();  String[] arr = (String[])list.toArray(new String[size]);//注:这里注意list.remove(index)是返回的删除的那个元素,而不是list,另外在remove()之后,后面的元素会自动覆盖到移除元素的位置上String s = list.remove(0);//关于替换相应的字符串或者字符String s = "sadgjhasd";//注意:这里的s.replace()返回一个新的数组,对**原来的数组不做任何改变!!**,所以一定要用原数组作为接受对象才能覆盖原数组做出响应的改变s = s.replace(原来的字符串或者字符,新的字符串或者字符);s = s.replaceAll(".", "/");//replaceAll和replace不一样,她的第一个**参数是正则表达式,其中“.”表示的是所有字符**,注意!!!//String.replace()是将替换所有的,同时也是对原来的String不做任何改变,也是需要用新的String去接受才行!!如果要替换指定位置的字符串,应该用StringBuffer.replace(start,end,String),而且它是自动在原字符串上做改动,不需要用其他对象做接受,还要注意下这里的start和end,是含start不含end,比如start=0;end=1,那么替换的就是0号位置上的元素StringBuffer sb = new StringBuffer(s);sb.replace(0, 0, "1");//TreeSet和TreeMap可以自动排序,直接往里扔数即可,内部自动排序,很强大!!TreeSet hs = new TreeSet();String s1 = "abf";String s2 = "acd";String s3 = "abc";hs.add(s1);hs.add(s2);hs.add(s3);System.out.println(hs);//Collections中提供了逆序的功能Collections.reverse(list);

4.数据库的范式问题

SQL语言又称为结构化查询语言
这里把常用的第一、二、三范式做一下说明:

1NF:第一范式,强调的是原子性,即列不能再分解为其他的列,比如表【联系人】:姓名、性别、电话,这张表是不满足1NF的,因为电话这一列一般还会分成公司电话、家庭电话,所以不满足1NF的原子性

2NF:第二范式,先必须满足1NF,强调的是其他属性对主键的完全依赖,主要是针对联合主键,如果是单一主键,满足1NF,那么这张表也必定满足2NF。如【选课关系】:学号, 姓名, 年龄, 课程名称, 成绩, 学分,关键字为组合【关键字学号, 课程名称】,这里可以【学分】只依赖于【课程名称】的,【姓名、年龄】则只依赖于【学号】。只有【成绩】是依赖于【学号和课程名称】的(这才是完全依赖),前两者的依赖不是完全依赖,所以这里的【选课关系】不满足2NF

3NF:必须满足2NF,并且不依赖其他非主属性,他们之间不存在依赖传递关系,通俗点讲,要求一个表中不包含已在其他表中包含的非主键关键字的信息。如一张表:学号、姓名、年龄、所在学院、学院地点、学院电话,关键字为【学号】,由于是单一的主键,首先他肯定是满足2NF的,然后看由于这里的【学院地点和学院电话】显然是依赖于【学院】这个属性的,但是学院地点和学院电话显然被包含在了这张表中了,所以不满足3NF。

5.方法的重写与重载

Java的方法重载,就是在类中可以创建多个方法,它们具有相同的名字,但具有不同的参数和不同的定义,方法重写的返回值类型必须相同或相容,总的来说,方法的重载除了方法名一样,其他的都有可能不一样,和返回值无关!(就是说如果仅仅是返回值类型不同,那么不能构成方法的重载)。调用方法时通过传递给它们的不同参数个数和参数类型来决定具体使用哪个方法, 这就是多态性。

Java方法的重写,子类中的方法与父类中的某一方法具有相同的方法名返回类型参数表,权限修饰符可以不一样,子类函数的访问修饰权限不能少于父类的,总的来说,方法的重写除权限(子类方法的权限必须大于等于父类中方法的权限)可以不一样,其他都必须一样。这里注意一下,静态方法不能被覆盖成非静态的方法

注意点:
第一种
这里写图片描述
第二种
这里写图片描述
这里第一种是静态的方法(图表标注错了,应该是两个getName()两个方法的static),他们存在于不同的内存中,具体执行那个主要是看是由哪个类调用的,所以她的输出为:Father、Father,记住如果方法声明为static的话,就看是具体调用对象。还有个注意的是就算这里改成

Father father = new Father();Child child = (Child)father;System.out.println(child.getName);

输出还是Father、Father,虽然不知道什么鬼解释,记着吧;
第二种如果调用的方法未声明为static,那就啥都不管,不管你把我声明父类还是子类,我只认new出来的对象,毕竟new Object()中的Object才是生我的对象呀,就是子类覆盖父类的方式,输出为Father、Child

6.中文编码问题

Java语言中,中文字符所占的字节数取决于字符的编码方式,一般情况下,采用ISO8859-1编码方式时,一个中文和一个英文字符都只占1个字节;采用GB2312或GBK编码方式时,一个中文字符占2个字节(java默认是这种编码);而采用UTF-8编码方式时,一个中文字符会占3个字节,java的char类型占两个字节默认使用GBK编码存储。这种写法是正确的,此外java还可以用中文做变量名
java中可以指定字符串的编码方式:new String(byte[],编码方式),如下

String a = "中午";String b = new String(a.getBytes(),"GBK");String c = new String(a.getBytes(),"UTF-8");

7.java中的集合类

Map不是Collection中的!,是同等级别,Vector和Hashtable支持线程同步(线程安全),JDK1.8 的 ConcurrentHashMap 采用CAS+Synchronized保证线程安全,除此之外,StringBuffer和Properties以及堆栈Stack也是线程安全的。
【总结】:
Vector、Hashtable、Stack、StringBuffer、Properties都是线程安全的,集合类中的 ArrayList 、 LinkedList 、 HashMap中,随机添加和删除元素时,ArrayList的表现更加快速

Vector和ArrayList的区别:都实现了List接口,代表链表的数据结构,Vector是线程安全的,由于它必须保证同步,所以它的效率不如ArrayList高

Collection
—–List
—–LinkedList 非同步
—-ArrayList 非同步,实现了可变大小的元素数组
—-Vector 同步(即支持线程同步)
——Stack
—–Set 不允许有相同的元素

Map
—–HashTable 同步,实现一个key–value映射的哈希表
—–HashMap 非同步,采用链地址法解决冲突
—–WeakHashMap 改进的HashMap,实现了“弱引用”,如果一个key不被引用,则被GC回收

8.Java的五大三粗

java三大特性:继承、封装、多态
java五大原则(其实是java设计模式的原则):
单一职责原则(SRP)
开放封闭原则(OCP)
里氏替换原则(LSP)
依赖倒置原则(DIP)
接口隔离原则(ISP)
没有抽象原则!!!

9.子类和父类

子类的构造方法总是先调用父类的构造方法,如果子类的构造方法没有明显地指明使用父类的哪个构造方法,子类就调用父类不带参数的构造方法。如果父类没有无参的构造函数,所以子类需要在自己的构造函数中显性的调用父类的构造函数,否则编译报错。

10.字节流和字符流的分辨

总结:所有以“InputStream”和“outputStream”结尾的都是字节流,所有以“Reader“和”writer“结尾的都是字符流

11.final、finally和finalize的区别

final:用于声明属性,方法和类,分别表示属性不可变,方法不可覆盖(重写),类不可继承,其中注意的是,在声明变量的时候,变量必须要初始化。另外,final方法是可以被重载的,但不可被重写
finally:是异常处理语句结构的一部分,表示总是执行。
finalize:是Object类的一个方法,在垃圾收集器执行的时候会调用被回收对象的此方法,可以覆盖此方法提供垃圾收集时的其他资源的回收,例如关闭文件等。

12.java中线程

Java 中的线程由一个虚拟处理机CPU执行的代码代码操作的数据等三部分组成,线程通信中,wait()、notify()和notifyAll()是 Object类 中的方法!!,线程的终止不能用stop,应该设置一个标识符,true的时候正常运行run方法

13.Java中的构造方法

普通的类方法是可以和类名同名的,和构造方法唯一的区分就是,构造方法没有返回值的,而且也不能带任何返回值的修饰,包括void(也不能包含void!!!)

14.Java中的equals()和==以及!=

通常来说,“==”和“!=”比较的都是内存地址,但这两个符号对于基本数据类型是比较的大小,不是地址,而equals比较的是内容的值是否相同,equals没重写时候和==一样,比较的是对象的地址,new 的两个对象各自地址不一样,使用equals比较为false,但是String类型中的equals方法Java默认重写了,可以比较对象里的值;两个对象指向的同一个String成员变量里的值相同,所以eqauals比较也相同,总结一开始都是比较的是内存地址,如果equals被重写或者用在String类型(java中默认在String类型是重写了equals方法)中的话,那么此时的equals比较的是他们的内容,而非内存!当”==”用于基本类型时候,是比较值是否相同;当用于引用类型的时候,是比较对象是否相同。”==”和”!=”比较的是地址 。这里需要说明的是Java中的自动装箱和拆箱的问题,因为这里可能涉及到int类型和Intege以及double和Double类型的比较(JDK1.5以上),基本数据类型和基本包装类型进行“==”运算符的比较,基本包装类型将会自动拆箱变为基本数据类型后再进行比较大小(如Integer和int,这时的Integer会自动变为int类型);两个基本型的封装型进行equals()比较,首先equals()会比较类型,如果类型相同,则继续比较值,如果值也相同,返回true;基本封装类型调用equals(),但是参数是基本类型,这时候,先会进行自动装箱,基本型转换为其封装类型

这里再提一下equals和hashcode的关系,一下内容务必好好理解:
关于hashcode的约定准则:
第一:在某个运行时期间,只要对象的(字段的)变化不会影响equals方法的决策结果,那么,在这个期间,无论调用多少次hashCode,都必须返回同一个散列码。
第二:通过equals调用返回true 的2个对象的hashCode一定一样。
第三:通过equasl返回false 的2个对象的散列码不需要不同,也就是他们的hashCode方法的返回值允许出现相同的情况。
总结一句话:等价的(调用equals返回true)对象必须产生相同的散列码。不等价的对象,不要求产生的散列码不相同

15.Java中的权限修饰符

权限从大到小依次是:public–>protected–>friendly(默认的包类权限)–>private,总结:公众保护友好的私人

16.Java中的异常

Java中所有的可不检测(unchecked)异常都来自RuntimeException类或其子类。

17.Java直至1.8并发框架中支持的锁

支持的锁有读写锁、自旋锁、乐观锁

18.匿名类

由于构造器的名字必须与类名相同,而匿名类没有类名,所以匿名类不能有构造器

19.this关键字

this不能在static的方法中使用!!

20.Servelt

J2EE中,当把来自客户机的HTTP请求委托给servlet时,会调用HttpServlet的service方法

21.ArrayList

初始化的时候,如果调用的是ArrayList(),那么默认是构造一个初始容量为 10 的空列表,然后不够的时候,就进行扩容,每次扩容1.5倍,这也就是ArrayList可以自动长度的原理;而ArrayList(int initialCapacity)是构造一个具有指定初始容量的空列表,这时候的初始容量就是initialCapacity,而不是10了;ArrayList是基于数组实现的,所以查询快,增删慢LinkedList是基于链表实现的,所以查找慢,增删快

22.webService

Webservice是跨平台跨语言远程调用技术;
它的通信机制实质就是xml数据交换,而非json
它采用了soap协议(简单对象协议)进行通信

23.Java中基本数据类型的转换

基本数据类型创建在栈中
(char(2字节)、byte、short)–>int(4个字节)–>long(8字节)–>float(4字节)–>double(8字节);(还有一个boolean合称8种基本数据类型)
【注意】
byte、short、int、long又叫做整数类型
float、double又叫做浮点数类型(或者叫实型)

另外也要注意基本数据类型和基本包装类型的区别,一个是基本数据类型,一个是类,一个放在栈中(基栈),一个放在堆中,其中注意一下boolean和Boolean,前者只有false和true,但是Boolean除了有true和false还有null。

24.Java中变量的存放

Java把内存分成两种,一种叫做栈内存,一种叫做堆内存,一些基本类型的变量和对象的引用变量都是在函数的栈内存中分配(基站!!);堆内存用于存放由new创建的对象和数组,在堆中分配的内存,由java虚拟机自动垃圾回收器来管理;还有一点需要注意的是类中的成员变量放在堆区方法中的局部变量放在栈区

25.关于抽象类(abstract)

1.抽象类中可以包含抽象方法(甚至可以不包含任何抽象成员),也可以包含非抽象方法,但是如果一个类中有抽象方法,那么这个类必须声明为抽象方法!!
2.抽象方法不能有方法体不能有{},一个类如果用了abstract修饰后,那么它肯定是用来被实现的,所以不能同时再出现static或者final这类的关键字;
3.接口中可以不声明任何方法,和成员变量;4.抽象类不能被实例化
5.抽象类可以被抽象类继承,结果还是抽象类;也可以被非抽象类继承,那这个非抽象类必须通过覆盖的方式来实现所有继承而来的成员
6.抽象类可以被声明,但是不能被实例化
7.当继承抽象类的时候,如果父类中含有抽象方法,那么子类一定要实现其抽象方法,否则不能通过编译

26.变量是否需要初始化的问题

成员变量有默认初始值,而局部变量没有初始值得。局部变量是指在某个方法中定义的变量,定义未初始化可以编译通过,但是如果再调用编译就会报错

27.Java中的接口

这里注意,java中的接口是一种特殊的抽象类,类可以实现多个接口,所以接口可以继承(或扩展)多个接口,而且这时候用的extends关键字,而不是implements!!
1.抽象方法不能有方法体,不能有{},但是抽象类中可以包含抽象方法和非抽象方法
2.接口里的方法只能用 public 和 abstract 修饰,如果你不写也没关系,默认的也是 public abstract 修饰.
3.接口中的变脸那个默认是public static final,他们是公共的、静态的、不能被修改的常量,比如下面的代码,编译是通过的,输出为10

public class A implements B{    public static void main(string args[]){        int i;        A a1=new  A();        i =a1.k;        System.out.printin(“i=”+i);    }}Interface B{    int k=10;}

【注意】这里顺带谈一下抽象类和接口的区别:抽象类是一种功能不全的类,接口是一个抽象方法和public static final(默认)类型的变量组成的集合,都不能实例化(可是声明但不可实例化),前者只能单继承,后者则是多实现

28.java中常量池的概念

java中基本类型的包装类的大部分都实现了常量池技术,这些类是Byte,Short,Integer,Long,Character,Boolean,另外两种浮点数类型的包装类则没有实现(Float和Double)。另外Byte,Short,Integer,Long,Character这5种整型的包装类也只是在对应值小于等于127时才可使用对象池,即不负责创建和管理大于127的这些类的对象。另外值得一说的是String类型也实现了常量池,不要主动new!!。举个例子来说,正常来说s和f是不同的对象,因为String类型在初始化的时候是相当于new String(“xx”)的,但是注意这里只要不是new()的方式,只要“xx”中的xx内容相同,那么它将会从常量池里取数据而不是重新new(“xx”),所以两者是相等的,而a和b则是不等的

String s = "sdf";String f = "sdf";String a = new String("sdf");String b = new String("sdf"); 

29.Java中的JVM

运行时数据区包括:栈、堆、方法区(这货是共享的其他都是私有、隔离的)、程序计数器

1.栈区线程私有(即线程隔离,下同),存放基本类型,对象的引用returnAddress ,在编译期间完成分配;
2.堆区 :也叫JAVA 堆、GC 堆,线程共享,存放对象的实例和数组, JAVA 堆是垃圾收集器管理的主要区域;
3.方法区线程共享,存储已被虚拟机加载的类信息,常量,静态变量,即时编译器编译后的代码等数据。这个区域的内存回收目标主要是针对常量池的对象的回收和对类型的卸载。
4.程序计数器线程私有,每个线程都有自己独立的程序计数器,用来指示下一条指令的地址。

30.java中的单例模式

//1.懒汉模式(线程不安全)public class Singleton {    private static Singleton instance;    private Singleton(){}    public static Singleton getInstance(){        if(instance==null) {            instance = new Singleton();        }        return instance;    }}//2.懒汉模式(线程安全)public class Singleton {    private Singleton instance;    private Singleton(){}    public static synchronized Singleton getInstance() {        if(instance==null) {            instance = new Singleton();        }        return instance;    } }

31.多维数组的定义

这里主要注意一下它的定义如何去写,总结:
等号的右边–不管几维数组,第一维的参数都是不可省,其他的第二维、第三维。。。第n维都是可省的,另外;
等号左边–数组名可以放在任意位置,如下例:

//二维数组的定义可以这么写int[][] arr = new int[2][];//也可以这么写int []arr[] = new int[2][];//还可以这么写int arr[][] = new int[2][];

32.java中的标识符命名规则

标识符是以字母开头的字母数字序列,这里的数字就是普通的数字,字母的概念包含了普通字母美元符号$以及下划线,其中需要注意的是也可以是Unicode字符集中的字符,如汉字

33.switch的成长(jdk7以上版本支持String类型)

java7之前,switch**只支持 byte、short、char、int或者其对应的封装类以及Enum类型**。在Java7中,呼吁很久的String支持也终于被加上了。在switch语句中,表达式的值不能是null,否则会在运行时抛出NullPointerException。在case子句中也不能使用null,否则会出现编译错误

34.volatile关键字

一旦一个共享变量(类的成员变量、类的静态成员变量)被volatile修饰之后,那么就具备了两层语义:
1)保证了不同线程对这个变量进行操作时的可见性,即一个线程修改了某个变量的值,这新值对其他线程来说是立即可见的。
2)禁止进行指令重排序。
volatile只提供了保证访问该变量时,每次都是从内存中读取最新值,并不会使用寄存器缓存该值——每次都会从内存中读取。
而对该变量的修改,volatile并不提供原子性的保证
由于及时更新,很可能导致另一线程访问最新变量值,无法跳出循环的情况,多线程下计数器必须使用锁保护。

35.java中的方法

java**不允许单独的过程或函数存在,java语言中的方法属于对象成员,而不是类(是静态的),静态方法才属于类成员**

36.java类中不能进行逻辑运算,只能是基本的初始化赋值,逻辑运算应该放在具体的方法体中!

public abstract class MyClass {     public int constInt = 5;     //1.这样的写法是错误的     constInt = constInt + 5;     //2.这样的方法也是错误的     public int a;     a = 5;     public void method() {     } } 

37.static初始化加载的问题

java中类的初始化顺序是: (父静–>子静–>父普–>子普)
1、初始化父类中的静态成员变量和静态代码块。
2、初始化子类中的静态成员变量和静态代码块。
3、初始化父类中的普通成员变量和代码块,在执行父类中的构造方法。
4、初始化子类中的普通成员变量和代码块,在执行子类中的构造方法。
其中静态块的执行顺序按照先声明先执行的原则,静态块JVM只执行一次

38.Java是如何管理内存的

java的内存管理就是对象的分配和释放问题。在java中,通过关键字new为每个对象申请内存空间(基本数据类型除外),所有的对象都在堆Heap中(基本数据类型在栈Stack中)。内存的分配由程序完成,内存的释放则是由GC完成,由此加重了JVM的工作,这也是java程序运行较慢的原因之一。释放对象的根本原则就是对象不再被引用了,这就要求GC监视每一个对象的运行状态。
【注意】进入DEAD的线程,它还可以恢复,GC不会回收

39.什么是java中的内存泄漏

内存泄漏就是存在一些被分配的对象,后续的过程中已经不再被使用,但是却不被GC回收仍然占用着内存。System.gc()方法不保证JVM的垃圾收集器一定会执行,仅仅是通知GC,但不是强迫他一定执行。造成内存泄露的原因就是忘记释放先前分配的内存,如果程序保留对永远不再使用的对象的引用,这些对象将会占用并耗尽内存,因为GC无法回收这些对象。通常通过将对象字段置为null或者从集合中移除来让GC自动回收该内存。
典型内存泄漏及其原因如下:
1.缓存
缓存就是一开始检验结果是否在缓存中,如果在就直接拿过来用,如果不在就去其他地方拿并把该结果放进缓存供下次使用。这个流程中潜在的内存泄漏可能在最后一步发生,因为如果调用该操作时有相当多的不同输入,就将有相当多的结果放进缓存。为了预防这样的情况,就必须确保缓存所使用的内存容量有一个上限,因此更好算法应该如下:检查结果是否在缓存中,如果在就直接拿过来用,如果没有就去其他地方拿,并将结果放进缓存,同时如果缓存所占的空间过大就移除缓存最久的结。
2.还有其他的。。。

40.关于clone

Object类有clone方法,但是Object又没有实现Cloneable接口,为什么?对于没有实现Cloneable接口的类来说,还可以用Object类中的clone方法实现一些基本的复制操作,那clone方法是不是并没有对对象是否属于cloneable类型进行验证?
解析:Object类的clone是protected的,不能直接调用,可以被子类调用,Object类的clone会知道对象大小,会为它分配空间,并将就对象的内容复制到新的对象中,但是clone方法执行前必须检查该类是否实现了Cloneable接口,如果没有将抛出CloneNotSupportedException的异常,这里需要注意的是Cloneable接口是一个标记接口,里面没有任何内容,仅仅是一个标记,实现了这个接口,执行clone方法才不会抛出异常,否则调用方法的时候不会抛出异常,但是执行这个方法的时候将抛出异常。另外clone()可以被未实现Cloneable接口的类的实例调用并不是说明没有进行验证,因为clone方法是从Object类继承而来,而Cloneable接口只是作为一个标记。

41.java中创建对象的几种方式

java中创建对象的几种方式
1.用new关键字创建对象,最常见
2.运用反射,调用java.lang.Class或者java.lang.reflect.Constructor类的new Instance()实例方法
3.调用Object类的clone的方法
4.运用反序列化手段,调用java.io.ObjectInputStream对象的readObject()方法
显然,第1、2两种方式都是会调用类的构造方法,第3种在内存上对已有对象的影印,所以不会调用构造函数,第4种从文件中还原类的对象,也不会调用构造函数,总结:创建对象并不一定调用构造函数

42.Java中用super调用父类构造函数时,为什么必须放在第一语句的位置?

如果不放在首句,那么super之前的语句就不太好处理了,因为super之前的语句肯定是为了满足某些行为,但是如果后面跟了super之后,继承父类的构造方法,那么前面所做的将变成无用功,又变成了父类的构造方法,这将是毫无意义的。

43.java中的正则

一般情况下,正则的形式有些是“+其他字符”的形式,但在java中所有的\都要改为\,否则将无法识别,其中注意单独的小数点.表示的是匹配除 “\n” 之外的任何单个字符。

44.线程安全中的synchronized和java.util.concurrent.locks.Lock的异同

Lock可以完成synchronized的所有功能,Lock有比synchronized更精确的线程语义和性能,synchronized会自动释放锁,而Lock必须要在finally中手动释放

45.Servlet的生命周期

Servlet的生命周期包括加载、实例化、初始化、处理请求、以及服务结束。web容器加载Servlet,生命周期开始,通过调用Servlet的init()方法进行Servlet的初始化,通过调用Service()方法实现根据请求的不同调用不同的方法,结束服务后,Web容器调用Servlet的destory()方法。

46.Servlet的单线程模式

要实现单线程,可以在配置文件中修改isThreadSafe属性,修改成这样:

<%@ page isThreadSafe="false"%>

Servlet页面间对象传递的方法有如下几种:通过request、Session、application、cookie等方法实现页面间的对象传递

47.会话跟踪技术

会话的作用域也就是Session,对于每个新的会话都会创建Session-scope对象,并且在会话结束后将其释放。web的会话机制可以通过Cookie机制、URL重写、Session机制实现会话

48.ArrayList、Vector、LinkedList的存储性能和特性

ArrayList和Vector都是使用数组方式存储数据,此数组元素大于实际存储的数据,Vector由于使用了synchronized方法,通常性能上比ArrayList差,而LinkedList使用了双向链表实现存储,按序号索引数据遍历,但是插入的时候只需要记录本项的前后项即可,所以插入快。

49.关于++以及–这个操作符

这一点本没有什么好讲的,唯一注意的是将进行过这种自加或者自减的操作之后赋值的对象,如果还是赋值给自身的话要特别注意了,一定要是不变的,比如说下面的例子

int i = 0;i = i++;System.out.println(i);

这里i++自加后还是赋给自身,这里注意i的值是不变的,最后i的值还是0,如果这里i=i++改成i=++i最后结果将变成1,说是啥内存中间机制;但是如果这里赋值给另一个变量比如j的话就是1了(和j=++i的结果一样),比如下面的代码段

int i = 0;int j = 0;j = i++;System.out.println(j);

这里输出的就是1了

50.Java中JVM的参数

JVM参数配置如下:-Xms1G -Xmx2G -Xmn500M -XX:MaxPermSize=64M -XX:+UseConcMarkSweepGC -XX:SurvivorRatio=3, 问eden区最终分配的大小是多少?
【解析】JVM堆内存包括年轻代,老年代和持久代。其中年轻代又包括一个Eden区和两个Survivor区。-Xmn500M表示年轻代大小是500M, -XX:SurvivorRatio=3表示Eden区与两个Survivor区的大小比值为3:1:1,故Eden区的大小为300M。这里对几个参数做如下说明:
-Xms:表示初始堆大小,默认物理内存的1/64,也是默认内存的最大值
-Xmx:表示最大堆大小,物理内存的1/4
-Xmn:年轻代大小(一个Edened区加两个Survivor区)
-XX:PermSize:设置持久代初始值
-XX:NewRatio:年轻代(包括Eden和两个Survivor区)与年老代的比值(除去持久代)
-XX:SurvivorRatio:Eden区与Survivor区的大小比值,这里注意包含了两个Survivor区,比如说该值为3,那么Eden:from:to=3:1:1

51.Hibernate中的POJO类对象的状态

这里的状态指的是Hibernate实体状态,主要三种状态,也即Hibernate在他生命期中的三种状态。
自由状态(Transient):实体在内存中自由存在,与数据库中的记录无关。有new语句开辟的java对象,如:Person p = new Person(“zhangsan”, “man”);如果没有变量对该对象引用,那他将被JVM回收。自由状态对象在内存中是独立存在的,他是信息载体,但和数据库无任何关联,可以通过Session的save()或saveOrUpdate()等方法将自由状态转变成持久化状态。

持久状态(Persistent):实体处于由Hibernate框架所管理的状态,对应了数据库中的一条记录,同时与某个session实例发生了关联。若用Session的delete()方法,对应的持久对象就变成了自由状态,因数据库中的记录已被删除,该对象将不在关联数据库中的任何记录。当Session执行close()或者clear()或者evict()方法,那持久状态将变成游离状态(托管状态),因为此时它已经不在Hibernate持久层的管理之下了。

游离状态(Detached):在session 关闭之后,可以使对象从持久状态转换到游离状态。
【注意】自由态、持久态、游离态两两相邻的状态是可以相互转化的,不能跨

52.Spring并没有提供日志系统,我们需要使用AOP和其他的东西比如说log4j来自己实现日志系统

53.Java中的变量

java中的变量分为三种:静态变量、成员变量和局部变量。静态变量是指在类中用static修饰的变量,生存周期由类决定(随类的加载而生成并初始化);成员变量是指在类中没有用static声明的变量,他属于该类的具体对象,生命周期由对象决定(随对象的加载而生成并初始化,随对象被垃圾回收器回收消失);局部变量是指方法中的变量或方法的参数,她的生命周期随方法的调用而创建、消亡而消亡。

54.Java中的内部类

内部类可分为4种:
(1)静态内部类:相当于外部类的静态成员,使用static修饰的内部类,隶属于外部类
(2)成员内部类:相当于外部类的普通成员,隶属于外部类的具体对象,在定义它的时候,需要先创建外部类对象,再创建它的实例
(3)局部内部类:定义在一个方法的方法体中,往往仅作为方法短暂的使用,只能访问final修饰的局部变量
(4)匿名内部类:定义在方法体中,但没有具体名字,具有非常大的灵活性,本质与局部内部类类似。

55.String、StringBuffer、StringBuilder的区别

首先String是不可变的,而StringBuffer是可变的,StringBuilder则和StringBuffer功能一样,只是StringBuffer是线程安全的,而StringBuilder不是线程安全的
【注意】
下面代码片的操作流程这这样的,由于String是不可变的,abcd则是先进行“a”+ “b”生成一个”ab”对象,再进行“ab”+ “c”生成“abc”对象,最后再进行“abc”+”d”操作得最终的对象,这个生最终的对象的过程中生成了”a”和“ab”以及”abc”这么三个中间并没有用到的字符串,使JVM增加负荷,严重影响其性能。

String abcd = "a" + "b" +"c";

56.关于Integer

Integer赋值为-128到127的时候,这个会被放在cache中,如果获取相同的数字的时候,将会从cache中取,他们的地址是一样的,但是如果超过了这个范围将会重新创建对象!如下

Integer i1 = 100;Integer i2 = 100;System.out.println(i1==i2);//在范围内所以输出为trueInteger i3 = 128;Integer i4 = 128;System.out.println(i3==i4);//此时不在范围内,输出为false

57.Jdk中jdbc连接数据库的设计模式

jdbc连接数据库使用的是桥接模式

58.关于Integer的方法

Integer.parseInt("...");//这个返回的是一个int变量Integer.valueOf("...");//这个返回的是Integer对象Integer.valueOf("...").intValue();//返回是int型变量

59.Hibernate中的get和load

Hibernate中,get方法在调用后立即向数据库发出SQL语句,返回持久化对象,若对象不存在,那么get会返回null,而load则是抛出ObjectNotFoundException;另外,get是直接从数据库中查询对象(立即发出SQL语句),而load方法Hibernate则是利用延迟机制加载这个对象,获取这个对象的一个代理(只含有该对象的id),当我们真正用到的才会发出sql语句。

60.JVM中GC回收方式所采用的算法

两个最基本的java回收算法:复制算法和标记清理算法
复制算法:两个区域A和B,初始对象在A,继续存活的对象被转移到B。此为新生代最常用的算法
标记清理:一块区域,标记要回收的对象,然后回收,一定会出现碎片,那么引出
标记-整理算法:多了碎片整理,整理出更大的内存放更大的对象
两个概念:新生代和年老代
新生代:初始对象,生命周期短的
永久代:长时间存在的对象
整个java的垃圾回收是新生代和年老代的协作,这种叫做分代回收。
P.S:Serial New收集器是针对新生代的收集器,采用的是复制算法
Parallel New(并行)收集器,新生代采用复制算法,老年代采用标记整理
Parallel Scavenge(并行)收集器,针对新生代,采用复制收集算法
Serial Old(串行)收集器,新生代采用复制,老年代采用标记整理
Parallel Old(并行)收集器,针对老年代,标记整理
CMS收集器,基于标记清理
G1收集器:整体上是基于标记 整理 ,局部采用复制

综上:新生代基本采用复制算法,老年代采用标记整理算法。cms采用标记清理。

90.杂记

1.-n=~n+1可推出~n=-n-1,其中-n表示相反数,~n表示是补码,妈的又忘了一次,该死!!!记住记住,再错揪你耳朵

2.计算42度的余弦值:double d=Math.cos(Math.toRadians(42))

3.Java中数组复制效率最高的是:System.arraycopy!!(不能再错了!!)

4.java中有三种移位运算符

<<      :     左移运算符,num << 1,相当于num乘以2>>      :     右移运算符,num >> 1,相当于num除以2>>>     :     无符号右移,忽略符号位,空位都以0补齐

这里需要注意的是,java中没有<<<这种移位符号

5.java编码的流程:Java编译后是字节码即byte code,运行的时候把字节码变成机器码。

6.在Java中,只有声明为static的方法才能不需要实例化对象直接调用,否则的话不能采用“类名.方法名”的形式来调用;static可以修饰内部类,外部类不允许声明为static,只有内部类才可以。另外static静态变量只能在类主体中定义,不能在方法中定义

7.不能有方法体,不能有大括号!

8.定义在同一个包(package)内的类可以不经过import而直接相互使用。

9.java调试器jdb.exe

10.拓扑排序是将结点按先后次序的约束排列,它只能用于有向无环图;内部排序是将关键码排序,这两种排序没什么关系

11.插入排序(包括希尔排序)一趟排序结束后不一定能够选出一个元素放在其最终位置上

原创粉丝点击