java 基础篇

1java语言的三种技术架构

J2EE:企业版。是为开发企业环境下的应用程序提供的一套解决方案。

该技术体系中包含的技术如ServletJsp等,主要针对于Web应用程序开发。

J2SE:标准版。是为开发普通桌面和商务应用程序提供的解决方案。

该技术体系是其他两者的基础,可以完成一些桌面应用程序的开发。比如Java版的扫雷。

J2ME:小型版。是为开发电子消费产品和嵌入式设备提供的解决方案。

该技术体系主要应用于小型电子消费类产品,如手机中的应用程序等。

2JVMJREJDK的区别?

JVM(Java Virtual Machine):java虚拟机,用于保证java的跨平台的特性。

java语言是跨平台,jvm不是跨平台的。

JRE(Java Runtime Environment):java的运行环境,包括jvm+java的核心类库。

JDK(Java Development Kit):java的开发工具,包括jre+开发工具

3java的跨平台性:

通过Java语言编写的应用程序在不同的系统平台上都可以运行。

跨平台的原因:只要在需要运行java应用程序的操作系统上,先安装一个Java虚拟机(JVM Java Virtual Machine)即可。由JVM来负责Java程序在该系统中的运行。

4、环境变量pathclasspath的作用是什么?

(1) path是配置Windows可执行文件的搜索路径,即扩展名为.exe的程序文件所在的目录,用于指定DOS窗口命令的路径。

(2) Classpath是配置class文件所在的目录,用于指定类搜索路径,JVM就是通过它来寻找该类的class类文件的。

5Java的访问控制符作用范围?

Public 公共的,所有类均可以访问。

Protected 受保护的,当前包和不同包子类可以访问。

Default 默认访问类型,当前包下可以访问。

Private 私有的,只有本类可以访问。

4&&&的区别?

1&&会出现短路,如果可以通过第一个表达式判断出整个表达式的结果,则不继续后面表达式的运算;只能操作boolean类型数据;

2&不会出现短路,将整个表达式都运算。既可以操作boolean数据还可以操作数。

5、标示符命名规则?

由数字(0-9),大小写英文字母,以及_$组成。

不能以数字开头。不能使用关键字来自定义命名。

6、数据类型?

(1)基本数据类型(48)

整数类型:byte(1)short(2)int(4)long(8)

浮点数类型:float(4)double(8)

字符类型:char(2)

布尔类型:boolean(ture false)(4)

(2)引用数据类型: 类、接口、数组

自动装箱:new Integer(6);底层调用Integer.valueOf(6)

自动拆箱:int i = new Integer(6);,底层调用i.intValue();方法实现。

7、类型转换

精度从高到低 double float long int short(char) byte 

(1)自动类型转换 将一个低精度---à高精度 

(2)强制类型转换 将一个高精度---à低精度(精度会下降)

8、常见的数据结构有? 数组,栈,队列,链表,树,图,堆

9、一个java类中包含那些内容? 属性、方法、内部类、构造方法、代码块。

10、那针对浮点型数据运算出现的误差的问题,你怎么解决?

使用Bigdecimal类进行浮点型数据的运算

11、一个".java"源文件中是否可以包括多个类(不是内部类)?有什么限制?

可以有多个类,但只能有一个public的类,并且public的类名必须与文件名相一致。

12、在JAVA如何跳出当前的多重嵌套循环?

Java中,要想跳出多重循环,可以在外面的循环语句前定义一个标号,然后在里层循环体的代码中使用带有标号的break 语句,即可跳出外层循环。

使用标签和break,并且应在所在循环的外层循环之前定义标签:

13switch语句能否作用在byte上,能否作用在long上,能否作用在String?

idk 1.7之前,switch只能支持byte, short, char, int或者其对应的封装类以及Enum类型。从idk 1.7之后switch开始支持Stringswitch中的参数不支持其他类型,例如long类型

14short s1 = 1; s1 = s1 + 1;有什么错? short s1 = 1; s1 += 1;有什么错?

对于short s1 = 1; s1 = s1 + 1; 由于s1+1运算时会自动提升表达式的类型,所以结果是int型,再赋值给short类型s1时,编译器将报告需要强制转换类型的错误。

对于short s1 = 1; s1 += 1;由于 += java语言规定的运算符,java编译器会对它进行特殊处理,因此可以正确编译。

14`(1<3)?"a":"b")+3+4``(1<3)?"a":"b")+(3+4)`区别

System.out.println(((1<3)?"a":"b")+3+4);  System.out.println(((1<3)?"a":"b")+(3+4));
控制台: a34   a7

15Math.round(11.5)等於多少? Math.round(-11.5)等於多少? 12 -11

16char型变量中能不能存贮一个中文汉字?为什么?

char型变量是用来存储Unicode编码的字符的,unicode编码字符集中包含了汉字,所以,char型变量中当然可以存储汉字啦。不过,如果某个特殊的汉字没有被包含在unicode编码字符集中,那么,这个char型变量中就不能存储这个特殊汉字。补充说明:unicode编码占用两个字节,所以,char类型的变量也是占用两个字节。

17charvarchar区别

都是用来存储字符串的,它们保存方式不一样,char有固定的长度,而varchar属于可变长的字符类型。

18charbyte的区别,各几个字节

    char类型是字符型 16个位 两个字节 没有符号位 16个位全部都是数值位,所以取值范围0到2的16次方-1

byte类型是整数类型当中的一种 8个位 一个字节 其中1个符号位 15个数值位,所以取值范围-2的15次方到+2的15次方-1

  1. 基础类型和包装类的区别?

1.声明方式不同:基本类型不使用new关键字,而包装类型需要使用new关键字。

2.存储方式及位置不同:基本类型是直接将变量值存储在栈中,而包装类型是将对象放在堆中,然后通过引用来使用;

3.初始值不同:基本类型的初始值如int0booleanfalse,而包装类型的初始值为null

4.使用方式不同:基本类型直接赋值直接使用就好,而包装类型在集合如CollectionMap时会使用到。

19、用最有效率的方法算出2乘以8等於几?   2 << 3

因为将一个数左移n位,就相当于乘以了2n次方,那么,一个数乘以8只要将其左移3位即可,而位运算cpu直接支持的,效率最高,所以,2乘以8等於几的最效率的方法是2 << 3

19foreach与正常for循环效率对比

对于for循环就是调用get(i)取得元素,而对于foreach是通过iterator实现的遍历,

对于数组来说forforeach循环效率差不多,对于链表来说for循环效率明显比foreach低。

对于ArrayList来说,它是通过一个数组实现的,可以随机存取;但是LinkedList是通过链表实现的,for循环时要获取第i个元素必须从头开始遍历,而iterator遍历就是从头开始遍历,遍历完只需要一次,所以for循环需要的时间远远超过for循环。 

20、数组实例化有几种方式?

静态实例化:创建数组的时候已经指定数组中的元素, int[] a=new int[]{1,3,3}

动态实例化:实例化数组的时候只指定了数组程度,数组中所有元素都是数组类型默认值

20、数组在内存中如何分配

1、简单的值类型的数组,每个数组成员是一个引用(指针),引用到栈上的空间(因为值类型变量的内存分配在栈上)

2、引用类型,类类型的数组,每个数组成员仍是一个引用(指针),引用到堆上的空间(因为类的实例的内存分配在堆上)

21java中是值传递引用传递?

值传递是对基本型变量而言的,传递的是该变量的一个副本,改变副本不影响原变量。
引用传递一般是对于对象型变量而言的,传递的是该对象地址的一个副本, 并不是原对象本身,当在一个方法操作参数的时候,其实操作的是引用所指向的对象。
一般认为,java内的传递都是值传递,java中实例对象的传递是引用传递 

传引用是指传递的是地址而不是值本身,传值则是传递值的一份拷贝。

22、假设把实例化的数组的变量当成方法参数,当方法执行的时候改变了数组内的元素,那么在方法外,数组元素有发生改变吗?

改变了,因为传递是对象的引用,操作的是引用所指向的对象

23、实例化数组后,能不能改变数组长度呢?

不能,数组一旦实例化,它的长度就是固定的

24、假设数组内有5个元素,如果对数组进行反序,该如何做?

创建一个新数组,从后到前循环遍历每个元素,将取出的元素依次顺序放入新数组中

25java创建对象的几种方式?

1).采用new   2).通过反射   3).采用clone   4).通过序列化机制

2者都需要显式地调用构造方法。造成耦合性最高的恰好是第一种,因此你发现无论什么框架,只要涉及到解耦必先减少new的使用。

26、变量有什么用?为什么要定义变量?什么时候用?

变量的作用:用来存储数据。

为什么要定义变量:用来不断的存放同一类型的常量,并可以重复使用

26、成员变量和局部变量的区别(重点)

(1)作用域

成员变量:针对整个类有效。

局部变量:只在某个范围内有效。(一般指的就是方法,语句体内)

(2)存储位置

成员变量:随着对象的创建而存在,随着对象的消失而消失,存储在堆内存中。

局部变量:在方法被调用,或者语句被执行的时候存在,存储在栈内存中。

当方法调用完,或者语句结束后,就自动释放。

(3)初始值

成员变量:有默认初始值。

局部变量:没有默认初始值,使用前必须赋值。

27、静态变量和实例变量的区别?

语法定义上:静态变量前要加static关键字,而实例变量前则不加。

程序运行时:实例变量属于某个对象的属性,必须创建了实例对象,其中的实例变量才会被分配空间,才能使用这个实例变量。静态变量不属于某个实例对象,而是属于类,所以也称为类变量,只要程序加载了类的字节码,不用创建任何实例对象,静态变量就会被分配空间,静态变量就可以被使用了。总之,实例变量必须创建对象后才可以通过这个对象来使用,静态变量则可以直接使用类名来引用。

28、全局变量和局部变量哪个能被覆盖

Java当中不允许定义全局变量。Java当中不存在全局变量的概念,只有类体当中的成员变量(实例变量)和方法体当中的局部变量覆盖是只有方法才存在的。子类继承得到父类方法后对其进行重新实现叫做方法覆盖.属性根本不存在覆盖

29、静态方法和实例方法的区别主要体现在两个方面:

在外部调用静态方法时,可以使用"类名.方法名"的方式,也可以使用"对象名.方法名"的方式。而实例方法只有使用"对象名.方法名"

调用静态方法可以无需创建对象。静态方法在访问本类的成员时,只允许访问静态成员(即静态成员变量和静态方法),而不允许访问实例成员变量和实例方法;实例方法则无此限制。

30、面向对象特点?封装继承和多态

封装:隐藏对象的属性和实现细节,仅对外提供公共访问方式。私有是封装的一种体现。用private关键字修饰。

继承: 多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中,那么多个类无需再定义这些属性和行为,只要继承那个类即可。用关键字extends

多态: 一个对象在程序不同运行时刻代表的多种状态,父类或者接口的引用指向子类对象。封装和继承是为多态做准备的。多态实现的机制是重写和重载。

多态前提A:存在继承或者实现关系B:有方法的重写C:父类(接口)引用指向子类(实现)对象

实现多态的技术为动态绑定。在执行期间判断所引用对象的实际类型,根据实际类型调用其相应方法。多态允许不同类的对象对同一消息做出响应,即同一消息可以根据发送对象不同采用多种不同的行为方式。(发送消息就是方法调用)。

多态作用:消除了类型之间的耦合关系。

31、虚拟机是如何实现多态的

动态绑定技术(dynamic binding),执行期间判断所引用对象的实际类型,根据实际类型调用对应的方法.

32、重写和重载区别?

重载:在同一类中。方法名相同,参数列表不同。重载可以改变返回类型。是一个类中多态性的体现。

重写:在不同类中(子父类中)。是父类和子类之间多态性体现。重写时访问控制权限不能更加严格,抛出异常(非运行时异常)种类不能更加规范。

33、接口和抽象类的区别

1)抽象类可以提供成员方法的实现细节,而接口中只能存在public abstract 方法;

2)抽象类中成员变量可以是各种类型的,而接口中成员变量只能是public static final类型;

3)接口中不能含有静态代码块以及静态方法,而抽象类可以有静态代码块和静态方法;

4)一个类只能继承一个抽象类,而一个类却可以实现多个接口。

5)抽象类中定义的是继承体系中的共性功能。接口中定义的是继承体系中的扩展功能。

6)抽象类被继承是"is a"关系:xx是yy的一种。接口被实现是"like a"关系:xx像yy的一种。

7)抽象类作为很多子类的父类,它是一种模板式设计。而接口是一种行为规范,它是一种辐射式设计

34、类和接口的区别?

  1. 接口类似于类,但接口的成员都没有执行方式,它只是方法、属性、事件和索引的集合。类除了这四种成员外还有别的成员(如字段)。
  2. 不能实例化一个接口,接口只包括成员的签名;类可以实例化(abstract类除外)。
  3. 接口没有构造方法,类有构造方法。
  4. 接口不能进行运算符的重载,类可以有运算符的重载。
  5. 接口的成员没有任何修饰符,其成员是公共的。类的成员可以有修饰符(如静态)。
  6. 派生于接口的类必须实现接口中所有成员的执行方式,而从类派生则不然。

34、接口有什么用

1、通过接口可以实现不相关类的相同行为,而不需要了解对象所对应的类。

2、通过接口可以指明多个类需要实现的方法。

3、通过接口可以了解对象的交互界面,而不需了解对象所对应的类。

另:Java是单继承,接口可以使其实现多继承的功能。

35、多态中对象调用成员的特点?

Fu f = new Zi();

A:成员变量   编译看左边,运行看左边

B:成员方法    编译看左边,运行看右边

C:静态方法   编译看左边,运行看左边

36、构造器Constructor是否可被override?

构造器Constructor不能被继承,因此不能重写Override,但可以被重载Overload

37、接口是否可继承接口抽象类是否可实现(implements)接口抽象类是否可继承实体类(concrete class)? 抽象类中是否可以有静态的main方法?

接口可以继承接口,接口间继承用extends。抽象类可以实现(implements)接口,但接口不能实现抽象类,抽象类间也可以用extends。抽象类可以继承实体类,但前提是必须有无参的构造方法。抽象类中可以有静态的main方法。

抽象类与普通类的唯一区别就是不能创建实例对象和允许有abstract方法。

38、构造方法能不能重载?能不能重写?可以重载,必须重写

39、如果父类只有有参构造方法,那么子类必须要重写父类的构造方法吗?

必须重写

40、创建一个子类对象的时候,那么父类的构造方法会执行吗?

会执行。当创建一个子类对象,调用子类构造方法的时候,子类构造方法会默认调用父类的构造方法。

41、写clone()方法时,通常都有一行代码,是什么?

clone 有缺省行为,super.clone();因为首先要把父类中的成员复制到位,然后才是复制自己的成员。

42、内部类可以引用它的包含类的成员吗?有没有什么限制?

完全可以。如果不是静态内部类,那没有什么限制!

如果你把静态嵌套类当作内部类的一种特例,那在这种情况下不可以访问外部类的普通成员变量,而只能访问外部类中的静态成员,

43Anonymous Inner Class (匿名内部类是否可以extends(继承)其它类,是否可以implements(实现)interface(接口)?

可以继承其他类或实现其他接口。不仅是可以,而是必须!

44、如果main方法被声明为private会怎样?

能正常编译,但运行的时候会提示”main方法不是public

45、如果去掉了main方法的static修饰符会怎样?

程序能正常编译。运行时会抛NoSuchMethodError异常。

46、为什么Java里没有全局变量?

全局变量是全局可见的,Java不支持全局可见的变量,因为:全局变量破坏了引用透明性原则。全局变量导致了命名空间的冲突。

49、父类的静态方法能否被子类重写  不能

子类继承父类后,有相同的静态方法和非静态,这是非静态方法覆盖父类中的方法(即方法重写),父类的该静态方法被隐藏(如果对象是父类则调用该隐藏的方法)

另外子类可继承父类的静态与非静态方法,至于方法重载我觉得它其中一要素就是在同一类中,不能说父类中的什么方法与子类里的什么方法是方法重载的体现。

50、如何把一段逗号分割的字符串转换成一个数组?

1.用正则表达式,代码大概为:String [] result = orgStr.split(“,”);

2.StingTokenizer ,代码为:StringTokenizer  tokener = StringTokenizer(orgStr,”,”);

51、数组有没有length()这个方法? String有没有length()这个方法?

数组没有length()这个方法,有length的属性。Stringlength()这个方法。

52、什么是不可变对象

不可变对象指对象一旦被创建,状态就不能再改变。

任何修改都会创建一个新的对象,如 StringInteger及其它包装类。

53、能否创建一个包含可变对象的不可变对象?

当然可以创建一个包含可变对象的不可变对象的,你只需要谨慎一点,不要共享可变对象的引用就可以了,如果需要变化时,就返回原对象的一个拷贝。

最常见的例子就是对象中包含一个日期对象的引用.

54String对象的intern()方法

intern()方法会首先从常量池中查找是否存在该常量值,如果常量池中不存在则现在常量池中创建,如果已经存在则直接返回。

55Object类中有哪些方法?列举3个以上。

toString()equalshashCodegetClassfinalizeclone, wait()notifynotifyAll

56String类中方法有?

和长度有关的方法  int length() 得到一个字符串的字符个数

和数组有关的方法

byte[] getBytes() 将一个字符串转换成字节数组

char[] toCharArray() 将一个字符串转换成字符数组

String[] split(String) 将一个字符串按照指定内容劈开

和判断有关的方法

boolean equals(String) 判断两个字符串的内容是否一模一样

boolean equalsIgnoreCase(String) 忽略大小写的比较两个字符串的内容是否一模一样 boolean contains(String) 判断一个字符串里面是否包含指定的内容

Boolean startsWith(String) 判断一个字符串是否以指定的内容开头

boolean endsWith(String) 判断一个字符串是否以指定的内容结尾

compareTo(String) 对字符串内容按字典顺序进行大小比较,通过返回的整数值指明当前字符串与参数字符串的大小关系。若当前对象比参数大则返回正整数,反之返回负整数,相等返回0。
compareToIgnore(String) 与compareTo方法相似,但忽略大小写。

和改变内容有关的方法

String toUpperCase() 将一个字符串全部转换成大写

String toLowerCase() 将一个字符串全部转换成小写

String replace(String,String) 将某个内容全部替换成指定内容

String replaceAll(String,String) 将某个内容全部替换成指定内容,支持正则

String repalceFirst(String,String) 将第一次出现的某个内容替换成指定的内容

String substring(int) 从指定下标开始一直截取到字符串的最后

String substring(int,int) 从下标x截取到下标y-1对应的元素

String trim() 去除一个字符串的前后空格

和位置有关的方法

char charAt(int) 得到指定下标位置对应的字符

int indexOf(String) 得到指定内容第一次出现的下标

int lastIndexOf(String) 得到指定内容最后一次出现的下标

字符串连接 concat(String) 连接到当前字符串的后面,效果等价于"+"

字符串与基本类型的转换

static short parseInt(String)   parseLong(String)   parseFloat(String)

parseDouble(String s) parseByte(String)  parseShort(String)

基本类型转换为字符串类型

static String  valueOf(boolean b)   valueOf(char c)   valueOf(int i)
valueOf(long l)    valueOf(float f)   valueOf(double d)

57、怎样将 GB2312 编码的字符串转换为 ISO-8859-1 编码的字符串?

  1. String s1 = "你好";
  2. String s2 = new String(s1.getBytes("GB2312"), "ISO-8859-1");

58、能不能自己写个类,也叫java.lang.String

public class String {

    public static void main(String[] args) {

        System.out.println("string");

    }

}

可以,但在应用的时候,需要用自己的类加载器去加载,否则,系统的类加载器永远只是去加载jre.jar包中的那个java.lang.String。由于在tomcatweb应用程序中,都是由webapp自己的类加载器先自己加载WEB-INF/classess目录中的类,然后才委托上级的类加载器加载,如果我们在tomcatweb应用程序中写一个java.lang.String,这时候Servlet程序加载的就是我们自己写的java.lang.String,但是这么干就会出很多潜在的问题,原来所有用了java.lang.String类的都将出现问题。 

59、使用final关键字修饰一个变量时,是引用不能变,还是引用的对象不能变?

使用final关键字修饰一个变量时,是指引用变量不能变,引用变量所指向的对象中的内容还是可以改变的。

60、说出一些常用的类,包,接口,请各举5

常用的类:BufferedReader,BufferedWriter,FileReader,FileWirter,String,Integer,java.util.Date,System,Class,List,HashMap
常用的包:java.langjava.iojava.utiljava.sqljavax.servletorg.apache.strtuts.actionorg.hibernate
常用的接口:Remote,List,Map,Document,NodeList,Servlet,HttpServletRequest,HttpServletResponse,Transaction(Hibernate),Session(Hibernate),HttpSession

61final,finally,finalize区别。

final是最终的意思。它可以用于修饰类,成员变量,成员方法。
它修饰的类不能被继承,它修饰的变量时常量,它修饰的方法不能被重写。

finally:是异常处理里面的关键字。
它其中的代码永远被执行。特殊情况:在执行它之前jvm退出。System.exit(0);

finalize:Object类中的一个方法。
它是于垃圾回收器调用的方式。

62final有哪些用法?

1).final修饰的不可以被继承

2).final修饰的方法不可以被重写

3).final修饰的变量不可以被改变。

如果修饰的引用,那么表示引用不可变,引用指向的内容可变。

4).final修饰的方法,JVM会尝试将其内联,以提高运行效率

5).final修饰的常量,在编译阶段会存入常量池中

当前回答出编译器对final域要遵守的两个重排序规则更好:

1).在构造函数内对一个final域的写入,与随后把这个被构造对象的引用赋值给一个引用变量,这两个操作之间不能重排序。

2).初次读一个包含final域的对象的引用,与随后初次读这个final域,这两个操作之间不能重排序

63StringStringBufferStringBuilder 的区别是什么?

1String:底层使用一个不可变的字符数组private final char value[];它内容不可变适用于少量的字符串操作的情况

stringBufferStringBuilder都继承了AbstractStringBuilder底层使用的是可变字符数组:char[] value;内容是可变的

StringBuilder:适用于单线程下在字符缓冲区进行大量操作的情况

StringBuffer:适用多线程下在字符缓冲区进行大量操作的情况

2、运行速度,或者说是执行速度,在这方面运行速度快慢为:StringBuilder > StringBuffer > String

3StringBuilder是线程不安全的,效率较高;而StringBuffer是线程安全的,效率较低。通过他们的append()方法来看,StringBuffer是有同步锁,而StringBuilder没有:

 

d. 1.字符串的底层都是基于char类型的数组实现的

2.当在字符串后面不断的追加新内容的时候,使用StringBuffer效率高,因为对于StringBuffer的对象来说底层开辟的数组对象会预留16块空间,当我们不断的在字符串的后面追加新的内容,他是在缓冲区里面追加,当缓冲区满了那么才开辟一个新的数组对象,然后再预留当前数组空间大小一半的空间当作缓冲区.

  3.对于一个String类型的对象来说,没有缓冲区的概念,当前字符串有多少个字符,底层数组就开辟多大空间,如果我们想在String类型的后面不断的追加新的内容的话,底层其实不断的在创建新的数组对象,相对来说创建数组的频率会高很多,效率较低。因为每次开辟新数组之后都需要复制老元素 改变引用指向 然后将来还要回收旧的数组...

64、判断两个对象是否相同,能使用equlas比较吗?

不能。Equlas大多用来做字符串比较,要判断基本数据类型或者对象类型,需要使用==

65==equals有什么区别?

==可以判断基本数据类型值是否相等,也可以判断两个对象指向的内存地址是否相同,也就是说判断两个对象是否是同一个对象,Equals通常用来做字符串比较。

==是运算符,用于比较两个值是否相等,而equalsObject类的方法,用于比较两个对象是否相等。默认Object类的equals方法是比较两个对象的内存地址,此时和==的结果一样,如果需要比较对象内容,需要重写equal方法。

66equals()hashcode()的区别

hashCode()是Object类的一个方法,返回一个哈希值。

如果两个对象根据equals()方法比较相等,那么调用这两个对象中任意一个对象的hashCode()方法必须产生相同的哈希值。

如果两个对象根据equals()方法比较不相等,那么产生的哈希值不一定相等(碰撞的情况下还是会相等的)。

67String 为什么是不可变的?

String 不可变是因为在 JDK 中 String 类被声明为一个 final 类,且类内部的 value 字节数组也是 final 的,只有当字符串是不可变时字符串池才有可能实现,字符串池的实现可以在运行时节约很多 heap 空间,因为不同的字符串变量都指向池中的同一个字符串;如果字符串是可变的则会引起很严重的安全问题,譬如数据库的用户名密码都是以字符串的形式传入来获得数据库的连接,或者在 socket 编程中主机名和端口都是以字符串的形式传入,

  1. 因为字符串是不可变的,所以它的值是不可改变的,否则黑客们可以钻到空子改变字符串指向的对象的值造成安全漏洞;
  2. 因为字符串是不可变的,所以是多线程安全的,同一个字符串实例可以被多个线程共享,这样便不用因为线程安全问题而使用同步,字符串自己便是线程安全的;
  3. 因为字符串是不可变的所以在它创建的时候 hashcode 就被缓存了,不变性也保证了 hash 码的唯一性,不需要重新计算,这就使得字符串很适合作为 Map 的键,字符串的处理速度要快过其它的键对象,这就是 HashMap 中的键往往都使用字符串的原因。

String类是final类故不可以继承。

68、为什么针对安全保密高的信息,char[] String 更好?

因为 String 是不可变的,一旦创建就不能更改,直到垃圾收集器将它回收才能消失,即使我们修改了原先的变量,实际上也是在内存中新建一个对象,原数据还是保留在内存中等待回收;而字符数组 char[] 中的元素是可以更改的,也就是说像密码等保密信息用完之后我们可以马上修改它的值而不留痕迹,从而相对于 String 有更好的安全性。

69、继承collection接口的:list,set,queue,sortedSet.

继承Map接口的

HashMap:无序存放,Key不重复,

HashTable:无序存放,Key不重复,

TreeMap:按Key排序,Key可重复,

IdentityHashMap:弱引用Map集合,

70ArrayListLinkedListList的区别?

List 是集合列表接口,ArrayList 和 LinkedList 都是 List 接口的实现类。

1ArrayListobject类型出始容量为10的,基于动态数组的数据结构,因为地址连续,一旦数据存储好了,查询操作效率会比较高(在内存里是连着放的),支持随机访问

因为地址连续, ArrayList要移动数据,所以插入和删除操作效率比较低。   

2LinkedList双向循环链表的数据结构, 同时实现了双端队列 Deque 接口,地址是任意的,所以在开辟内存空间的时候不需要等一个连续的地址,对于新增和删除操作addremoveLinedList比较占优势,不支持随机访问,使用下标访问一个元素

ArrayList 的时间复杂度是 O(1),而 LinkedList O(n)

适用场景分析:

当需要对数据进行对此访问的情况下选用ArrayList

当需要对数据进行多次增加删除修改时采用LinkedList

70HashMap Hashtable 的区别?

HashMap 继承自 AbstractMap,Hashtable 继承自 Dictionary 类,两者都实现了 Map 接口;

1、对于null的处理不同

     HashMap无论是主键还是值都能存放null,但是由于主键要求唯一,所以主键只能存放一个null,但是值能存放多个空。

     Hashtable无论是主键还是值都不能添加null,会触发空指针异常。

2、同步特性不同

    HashMap同一时间允许多个线程同时进行访问,线程不安全,效率相对较高,但是可能出现并发错误。

    Hashtable底层大量的使用了synchronized修饰方法,同一时间只允许一个线程对其操作,线程安全,效率相对较低,但是不会出现并发错误。

    从jdk5.0开始集合的工具类Collections当中出现了一个静态方法synchronizedMap方法可以将一个不安全的map变成线程安全的。

    在高并发的场景下推荐使用java.util.concurrent.ConcurrentHashMap 有更高的性能

3、底层实现的区别

    HashMap分组组数可以指定,默认分为16个小组,但是最终的分组组数一定是2的n次方数,在计算散列的时候,底层使用&(分组组数-1)  [按位与运算]

    Hashtable分组组数可以随意指定,默认分11组,可以随意指定分组模分组组数

4、出现的版本不同   HashMap jdk1.2     Hashtable jdk1.0

5、迭代器不同

HashMap迭代器(Iterator)是fail-fast迭代器,Hashtable的enumerator迭代器不是fail-fast

什么是fail-fast? 就是最快的时间能把错误抛出而不是让程序执行

70、如何保证线程安全又效率高?

Java 5提供了ConcurrentHashMap,它是HashTable的替代,比HashTable的扩展性更好。

ConcurrentHashMap将整个Map分为N个segment(类似HashTable),可以提供相同的线程安全,但是效率提升N倍,默认N为16。

70、我们能否让HashMap同步?

HashMap可以通过下面的语句进行同步:Map m = Collections.synchronizeMap(hashMap);

70Hashtablesize()方法中明明只有一条语句”return count”,为什么还要做同步?

synchronize锁住整个Hashtable对象,避免在你取count的时候有其他线程修改这个Hashtable的count值。

71List集合取交集、并集、去除重复数据等

取交集:listA.retainAll(listB);

取并集:1.listA.removeAll(listB);  2.listA.addAll(listB);

取差集:listA.removeAll(listB);

72poll()方法和remove()方法区别?

poll() 和 remove() 都是从队列中取出一个元素,但是 poll() 在获取元素失败的时候会返回空,但是 remove() 失败的时候会抛出异常。

73、遍历list的时候为什么不能修改呢

使用for循环.增强for循环foreach、Iterator遍历集合时,不能对集合做添加和删除操作:

1.在遍历时往数组增加数据,会导致遍历不完整(因为增加了新成员长度变了),或者死循环(因为总是有新的进去)。

2.在遍历时删除数据,则会导致数组访问越界(因为长度缩短了,指针指向了一个已经标示为空的区域)否则会引发ConcurrentModificationException异常。

74Arraylist 的动态扩容机制是如何自动增加的?简单说说你理解的流程?

当在 ArrayList 中增加一个对象时 Java 会去检查 Arraylist 以确保已存在的数组中有足够的容量来存储这个新对象(默认为 10,最大容量为 int 上限,减 8 是为了容错),如果没有足够容量就新建一个长度更长的数组(原来的1.5倍),旧的数组就会使用 Arrays.copyOf 方法被复制到新的数组中去,现有的数组引用指向了新的数组。

75、为什么ArrayList增加或删除操作相对来说效率比较低?为什么?

ArrayList 在小于扩容容量的情况下其实增加操作效率是非常高的,在涉及扩容的情况下添加操作效率确实低,删除操作需要移位拷贝,效率是低点。因为 ArrayList 中增加(扩容)或者是删除元素要调用 System.arrayCopy 这种效率很低的方法进行处理,所以如果遇到了数据量略大且需要频繁插入或删除的操作效率就比较低了,具体可查看 ArrayList 的 add 和 remove 方法实现,但是 ArrayList 频繁访问元素的效率是非常高的,因此遇到类似场景我们应该尽可能使用 LinkedList 进行替代效率会高一些。

76、简单说说 Array ArrayList 的区别?

Array 可以包含基本类型和对象类型,ArrayList 只能包含对象类型;Array 的大小是固定的,ArrayList 的大小是动态变化的;ArrayList 提供了更多的方法和特性,譬如 addAll()、removeAll()、iterator() 等。

77、简单说说 Iterator ListIterator 的区别?

  • ListIterator 有 add() 方法,可以向 List 中添加对象,而 Iterator 不能。
  • ListIterator 和 Iterator 都有 hasNext() 和 next() 方法,可以实现顺序向后遍历,但是 ListIterator 有 hasPrevious() 和 previous() 方法,可以实现逆向(顺序向前)遍历,Iterator 就不可以。
  • ListIterator 可以定位当前的索引位置,通过 nextIndex() 和 previousIndex() 可以实现,Iterator 没有此功能。
  • 都可实现删除对象,但是 ListIterator 可以实现对象的修改,通过 set() 方法可以实现,Iterator 仅能遍历,不能修改。
  • ListIterator 是 Iterator 的子接口。

注意:容器类提供的迭代器都会在迭代中间进行结构性变化检测,如果容器发生了结构性变化,就会抛出 ConcurrentModificationException,所以不能在迭代中间直接调用容器类提供的 add、remove 方法,如需添加和删除,应调用迭代器的相关方法。

78、如何优雅的删除列表区间,譬如有一个 List 里面有 100 个元素,现在想删除 30 50 之间的元素,怎么写代码最优雅?    list.subList(30, 50).clear();

81Collections.emptyList() new ArrayList() 有什么区别?

相同点为都是 AbstractList 的子类,都可以序列化。

区别为 Collections.emptyList() 返回一个不可变的 List,而new ArrayList() 返回的 List 是可变的。只有当确实需要返回一个不可变空 List 时才使用 Collections.emptyList(),多次调用 Collections.emptyList() 只会返回同一个 List实例,而多次调用 new ArrayList() 每次都会返回新的实例。对于 emptySet() 和 emptyMap() 等类似方法有同样的结论适用。

82ArrayList LinkedList 使用普通 for 循环遍历谁快谁慢?为什么?

ArrayList 比 LinkedList 使用普通 for 循环遍历快,

ArrayList 的 get 方法只是通过数组下标从数组里面拿一个元素而已,所以 get 方法的时间复杂度是 O(1) 常数,和数组的大小没有关系,只要给定数组的位置就能定位到数据,而 Java 中 ArrayList 是基于数组实现的,数组是内存地址连续的空间,取值其实是地址的偏移,所以自然块的多。

LinkedList 是双向链表,所以 node 方法里面的 if 判断条件是在计算 index 在前一半还是后一半,然后决定是前序遍历还是后序遍历,这样二分法遍历查找会快很多,但是在 for 循环里面 LinkedList 在 get 任何一个位置元素时都会把前面的元素走一遍,随着 LinkedList 的容量越大这个遍历也就越大,所以其遍历的时间复杂度为 O(N/2),N 为 LinkedList 的容量,所以自然效率就比较低了。

83、为什么说集合的不同列表应该选择不同的遍历方式,举例谈谈你的认识?

ArrayList直接通过数组来进行存储,所以在使用下标的方式循环遍历的时候性能最好,通过下标可以直接取数据,速度最快,而且由于 ArrayList 是实现了 RandomAccess 接口(随机存取),这个接口是一个标记接口,表明了 ArrayList 集合的数据元素之间没有关联,位置间没有索引依赖。而如果对于 ArrayList 使用 for-each 或者迭代器进行遍历就没有 index 索引遍历效率高了,因为迭代器强制将 RandomAccess 的 ArrayList 建立了前后遍历关系,且在每次遍历过程中进行了一堆判断,所以相对来说对于 ArrayList 来说遍历使用普通 index 比迭代器要效率高些,但是差距不是十分明显。

LinkedList其为双向链表的实现存储,前后元素是通过链表索引建立关联的,无法直接取到对应的下标,因此在使用普通的 index 索引下标遍历时就需要计算对应的元素在哪,二分法决定头部还是尾部遍历,然后一步步的遍历找到元素,所以在遍历中每次都要从头查找元素位置,十分低效率。而迭代器的实现就是指向下一个元素,迭代器直接通过 LinkedList 的指针进行遍历,一次遍历就能找到每个合适的元素,所以 LinkedList 在使用迭代器遍历时效率最高

总之就是对于不同数据结构实现的集合列表就应该选择不同的遍历方式,尤其是 LinkedList 一定不要使用普通索引下标方式遍历,其效率极低。

84、请使用 LinkedList 模拟一个堆栈或队列的数据结构?

首先堆栈是先进后出,队列是先进先出,LinkedList 不但实现了 List 接口还实现了 Deque 双端队列接口,接着给出实现如下。

  1. public class Queue {
  2.     private LinkedList link;
  3.     public Queue() {
  4.         link = new LinkedList();
  5.     }
  6.     public void push(Object obj) {
  7.         link.addLast(obj);
  8.     }
  9.     public Object pop() {
  10.         return link.removeFirst();  //队列
  11.         //return link.removeLast(); //堆栈
  12.     }
  13.     public boolean isEmpty() {
  14.         return link.isEmpty();
  15.     }
  16. }

85、谈谈你理解的 LinkedList 工作原理和实现?

LinkedList 是以双向链表实现,链表无容量限制(但是双向链表本身需要消耗额外的链表指针空间来操作),其内部主要成员为 first 和 last 两个 Node 节点,在每次修改列表时用来指引当前双向链表的首尾部位,所以 LinkedList 不仅仅实现了 List 接口,还实现了 Deque 双端队列接口(该接口是 Queue 队列的子接口),故 LinkedList 自动具备双端队列的特性,当我们使用下标方式调用列表的 get(index)、set(index, e) 方法时需要遍历链表将指针移动到位进行访问(会判断 index 是否大于链表长度的一半决定是首部遍历还是尾部遍历,访问的复杂度为 O(N/2)),无法像 ArrayList 那样进行随机访问。(如果i>数组大小的一半,会从末尾移起),只有在链表两头的操作(譬如 add()、addFirst()、removeLast() 或用在 iterator() 上的 remove() 操作)才不需要进行遍历寻找定位。具体感兴趣可以去看下 LinkedList 的源码。

86HashMap底层扩容机制

     每次扩容的时候分组组数会直接*2 也就是变成原本的2倍大小 例如默认16组那么扩容一次之后变成32组

     首先HashMap构造方法可以传入两个参数,分别是int类型的分组组数和float类型的加载因子

     而其扩容跟阈值有关 只是在不同的JDK版本当中HashMap的实现也有区别.    

     所谓阈值 = 分组组数*加载因子 = 这是HashMap达到扩容条件的最小临界值

     *:当然在不同的JDK7.0当中,即便达到或者超过阈值,如果新元素要去的小组不为空,也会暂时不扩容

     以默认的分组组数16和加载因子0.75F为例 也就是Map<String,Integer> map = new HashMap<>();

     那么阈值就是12 也就是第13个元素添加的时候可能会导致扩容,那么底层将从分16组变成分32组 然后所有元素进行重新散列

     毫无疑问,重新散列会消耗时间,在使用HashMap的时候我们应该让分组组数*加载因子>总共要存放的键值对总量

     以避免添加过程当中触发扩容操作

87、怎么提高HashMap的效率

     考你分组组数和加载因子

     我们可以让HashMap底层开辟更多的分组,然后在元素总量不变的情况下,分组组数越多每一组元素个数自然越少,效率自然越高

     HashMap构造方法是可以传参数指定分组组数和加载因子(又名装填因子)的,

     这两者相乘得到阈值也就是达到扩容条件的最小临界值

     我们使用HashMap应该在知道元素总量的情况下保证分组组数*加载因子>元素总量 从而避免添加过程当中触发扩容操作影响效率

     另外在这个条件成立的前提下只需要

     分组组数越大,数据将被散列到越多个小组,查找效率越高

      加载因子越小,扩容会发生的越早,也就是在尽可能的保证效率

88HashMap如何调整性能和空间的取舍?

    构造方法的两个参数:int 分组组数 , float 加载因子

    在加载因子不变的情况下 如果我们让分组组数变大

        则效率更高 -> 但是需要更多的空间

    在分组组数不变的情况下 如果让加载因子变大

        则更加节省空间 -> 但是效率更低

    *:我们在已经知道要存放的元素个数的前提下 应该让

        分组组数*加载因子 > 元素总量     避免添加过程当中触发扩容操作

88HashMap结构

Node<K,V>:链表节点,包含了keyvaluehashnext指针四个元素。

tableNode<K,V>类型的数组,里面的元素是链表,用于存放HashMap元素的实体(table数组的大小,缺省值为16)。

size:记录了放入HashMap的元素个数。

loadFactor:负载因子(缺省值为0.75)。

threshold:阈值,决定了HashMap何时扩容,以及扩容后的大小,一般等于table大小乘以loadFactor

简单来说,HashMap由数组+链表组成的,数组是HashMap的主体,链表则是主要为了解决哈希冲突而存在的,如果定位到的数组位置不含链表(当前entrynext指向null,那么对于查找,添加等操作很快,仅需一次寻址即可;如果定位到的数组包含链表,对于添加操作,其时间复杂度为O(n),首先遍历链表,存在即覆盖,否则新增;对于查找操作来讲,仍需遍历链表,然后通过key对象的equals方法逐一比对查找。所以,性能考虑,HashMap中的链表出现越少,性能才会越好。

88HashMap什么时候扩容

当向容器添加元素的时候,会判断当前容器(table数组)的元素个数,如果大于等于阈值,即当前数组的长度乘以加载因子(缺省值为0.75)的值的时候,就要自动扩容啦。

89HashMap的实现原理

1 HashMap概述: HashMap是基于哈希表的Map接口的非同步实现。此实现提供所有可选的映射操作,并允许使用null值和null键。此类不保证映射的顺序,特别是它不保证该顺序恒久不变。

2 HashMap的数据结构:在java编程语言中,最基本的结构就是两种,一个是数组,另外一个是模拟指针(引用),所有的数据结构都可以用这两个基本结构来构造的,HashMap也不例外。HashMap实际上是一个链表散列的数据结构,即数组和链表的结合体。

当我们往Hashmapput元素时,首先根据keyhashcode重新计算hash,根绝hash值得到这个元素在数组中的位置(下标),如果该数组在该位置上已经存放了其他元素,那么在这个位置上的元素将以链表的形式存放,新加入的放在链头,最先加入的放入链尾.如果数组中该位置没有元素,就直接将该元素放到数组的该位置上.

90HashMap是如何工作的?

HashMap是一个针对数据结构的键值,每个键都会有相应的值,关键是识别这样的值。

HashMap 基于 hashing 原理,我们通过 put () get ()方法储存和获取对象。当我们将键值对传递给 put ()方法时,它调用键对象的 hashCode ()方法来计算 hashcode,让后找到 bucket 位置来储存值对象。当获取对象时,通过键对象的 equals ()方法找到正确的键值对,然后返回值对象。HashMap 使用 LinkedList 来解决碰撞问题,当发生碰撞了,对象将会储存在 LinkedList 的下一个节点中。 HashMap 在每个 LinkedList 节点中储存键值对对象。

90Hashmap如何同步?

当我们需要一个同步的HashMap时,有两种选择:

1、使用Collections.synchronizedMap..)来同步HashMap

2、使用ConcurrentHashMap

这两个选项之间的首选是使用ConcurrentHashMap,这是因为我们不需要锁定整个对象,以及通过ConcurrentHashMap分区地图来获得锁。

90、说一下hashmap以及它是否线程安全

HashMap基于哈希表的 Map 接口的实现。HashMap中,null可以作为键,这样的键只有一个;可以有一个或多个键所对应的值为nullHashMaphash数组的默认大小是16,而且一定是2的指数。HashtableHashMap都使用了 Iterator。而由于历史原因,Hashtable还使用了Enumeration的方式 HashMap 实现 Iterator,支持fast-fail

哈希表是由数组+链表组成的,它是通过把key值进行hash来定位对象的,这样可以提供比线性存储更好的性能。HashMap不是线程安全的。

 

91List,Map,Set三个接口,存取元素时各有什么特点?

list:有序的 可重复的 访问:可以for循环,foreach循环,iterator迭代器 迭代。
set:无序的 不重复的 访问:可以foreach循环,iterator迭代器 迭代
map:存储的是一对一对的映射 ”key=value“,key值 是无序,不重复的。value值可重复

访问:可以map中key值转为为set存储,然后迭代这个set,用map.get(key)获取value,也可以 转换为entry对象 用迭代器迭代

92、什么是 Vector Stack,各有什么特点?

Vector 是线程安全的动态数组,同 ArrayList 一样继承自 AbstractList 且实现了 List、RandomAccess、Cloneable、Serializable 接口,内部实现依然基于数组,Vector 与 ArrayList 基本是一致的,唯一不同的是 Vector 是线程安全的,会在可能出现线程安全的方法前面加上 synchronized 关键字,其和 ArrayList 类似,随机访问速度快,插入和移除性能较差(数组原因),支持 null 元素,有顺序,元素可以重复,线程安全。

Stack 是继承自 Vector 基于动态数组实现的线程安全栈,不过现在已经不推荐使用了,Stack 是并发安全的后进先出,实现了一些栈基本操作的方法(其实并不是只能后进先出,因为继承自 Vector,所以可以有很多操作,严格说不是一个栈)。

其共同点都是使用了方法锁(即 synchronized)来保证并发安全的。

92、简单说说 ArrayList Vector 的区别?

ArrayList 在默认数组容量不够时默认扩展是 1.5 倍,Vector 在 capacityIncrement 大于 0 时扩容 capacityIncrement 大小,否则扩容为原始容量的 2 倍。具体感兴趣可以去看二者源码。

1、Vector的方法都是同步的,是线程安全的,而ArrayList的方法不是,由于线程的同步必然要影响性能。因此,ArrayList的性能比Vector好。 
2、当Vector或ArrayList中的元素超过它的初始大小时,Vector会将它的容量翻倍,而ArrayList只增加50%的大小。 ArrayList就有利于节约内存空间。

3、大多数情况不使用Vector,因为性能不好,但是它支持线程的同步,即某一时刻只有一个线程能够写Vector,避免多线程同时写而引起的不一致性。

4、Vector可以设置增长因子,而ArrayList不可以。

适用场景分析:

1、Vector是线程同步的,所以它也是线程安全的,而ArrayList是线程异步的,是不安全的。如果不考虑到线程的安全因素,一般用ArrayList效率比较高。

2、如果集合中的元素的数目大于目前集合数组的长度时,在集合中使用数据量比较大的数据,用Vector有一定的优势。

93、为什么现在都不提倡使用 Vector 了?

因为 Vector 实现并发安全的原理是在每个操作方法上加锁,这些锁并不是必须要的,在实际开发中一般都是通过锁一系列的操作来实现线程安全,也就是说将需要同步的资源放一起加锁来保证线程安全,如果多个 Thread 并发执行一个已经加锁的方法,但是在该方法中又有 Vector 的存在,Vector 本身实现中已经加锁了,双重锁会造成额外的开销,即 Vector 同 ArrayList 一样有 fail-fast 问题(即无法保证遍历安全),所以在遍历 Vector 操作时又得额外加锁保证安全,还不如直接用 ArrayList 加锁性能好,所以在 JDK 1.5 之后推荐使用 java.util.concurrent 包下的并发类。此外 Vector 是一个从 JDK1.0 就有的古老集合,那时候 Java 还没有提供系统的集合框架,所以在 Vector 里提供了一些方法名很长的方法(如 addElement(Object obj),实际上这个方法和 add(Object obj) 没什么区别),从 JDK1.2 以后 Java 提供了集合框架,然后就将 Vector 改为实现 List 接口,从而导致 Vector 里有一些重复的方法。

97、如何把一个map做成线程安全的。

如果需要使 Map 线程安全,大致有这么四种方法:

1、使用 synchronized 关键字,代码如下

synchronized(anObject) {

  value = map.get(key);

}

2、使用 JDK1.5提供的锁(java.util.concurrent.locks.Lock)。代码如下

   lock.lock();

   value = map.get(key);

   lock.unlock();

3、使用 JDK1.5 提供的读写(java.util.concurrent.locks.ReadWriteLock)。代码如下

   rwlock.readLock().lock();

   value = map.get(key);

   rwlock.readLock().unlock();

   这样两个读操作可以同时进行,理论上效率会比方法 2 高。

4、使用 JDK1.5 提供的 java.util.concurrent.ConcurrentHashMap 。该类将 Map 的存储空间分为若干块,每块拥有自己的锁,大大减少了多个线程争夺同一个锁的情况。代码如下

    value = map.get(key); //同步机制内置在 get 方法中

比较:

 

   1、不同步确实最快,与预期一致。

   2、四种同步方式中,ConcurrentHashMap 是最快的,接近不同步的情况。

   3、synchronized 关键字非常慢,比使用锁慢了两个数量级。如果需自己实现同步,则使  用 JDK1.5 提供的锁机制,避免使用 synchronized 关键字。

98、不知道一个map集合的大小的情况下,怎么把它遍历出来(或者问Map是怎么取值的)

import java.util.*;

public class Test{

        public static void main(String[] args){

                 Map<Object,Object> map = new HashMap<Object,Object>();

                 Set<Object> set = map.keySet();

                 for(Object key:set){

                         System.out.println("遍历map   key="+key+"  value"+map.get(key));

                 }

                 Collection<Object> coll = map.values();

                 for(Object value:coll){

                         System.out.println("遍历map  这种方式不方便拿key  value"+value);

                 }

                 Set<Map.Entry<Object,Object>> sme = map.entrySet();

                 for(Map.Entry<Object,Object> entry:sme){

                         System.out.println("遍历map key="+entry.getKey()+"  value"+entry.getValue());

                 }

        }

}

99ConcurrentHashMap的原理

底层采用分段的数组+链表实现,线程安全

通过把整个Map分为NSegment,可以提供相同的线程安全,但是效率提升N倍,默认提升16倍。(读操作不加锁,由于HashEntryvalue变量是volatile的,也能保证读取到最新的值。)

Hashtablesynchronized是针对整张Hash表的,即每次锁住整张表让线程独占,ConcurrentHashMap允许多个修改操作并发进行,其关键在于使用了锁分离技术

有些方法需要跨段,比如size()containsValue(),它们可能需要锁定整个表而而不仅仅是某个段,这需要按顺序锁定所有段,操作完毕后,又按顺序释放所有段的锁

扩容:段内扩容(段内元素超过该段对应Entry数组长度的75%触发扩容,分段扩容,不会对整个Map进行扩容),插入前检测需不需要扩容,有效避免无效扩容。

就是重新计算容量,向HashMap对象里不停的添加元素,而HashMap对象内部的数组无法装载更多的元素时,对象就需要扩大数组的长度,以便能装入更多的元素。当然Java里的数组是无法自动扩容的,方法是使用一个新的数组代替已有的容量小的数组,就像我们用一个小桶装水,如果想装更多的水,就得换大水桶。

100ConcurrentHashMap怎么保证线程安全

ConcurrentHashMap是使用了锁分段技术来保证线程安全的:

首先将数据分成一段一段的存储,然后给每一段数据配一把锁,当一个线程占用锁访问其中一个段数据的时候,其他段的数据也能被其他线程访问。

ConcurrentHashMap提供了与HashtableSynchronizedMap不同的锁机制。Hashtable中采用的锁机制是一次锁住整个hash,从而在同一时刻只能由一个线程对其进行操作;而ConcurrentHashMap中则是一次锁住一个桶。

ConcurrentHashMap默认将hash表分为16个桶,诸如getputremove等常用操作只锁住当前需要用到的桶。这样,原来只能一个线程进入,现在却能同时有16个写线程执行,并发性能的提升是显而易见的。

通过把整个Map分为NSegment,可以提供相同的线程安全,但是效率提升N倍,默认提升16倍。

101、极高并发下HashTableConcurrentHashMap哪个性能更好

ConcurrentHashMap是使用了锁分段技术来保证线程安全,将hash表分为16个桶,诸如getputremove等常用操作只锁住当前需要用到的桶,效率提升16倍。

它们都可以用于多线程的环境,但是当Hashtable的大小增加到一定的时候,性能会急剧下降,因为迭代时需要被锁定很长的时间。因为ConcurrentHashMap引入了分割(segmentation),不论它变得多么大,仅仅需要锁定map的某个部分,而其它的线程不需要等到迭代完成才能访问map。简而言之,在迭代的过程中,ConcurrentHashMap仅仅锁定map的某个部分,而Hashtable则会锁定整个map

102、什么是快速失败的故障安全迭代器?

快速失败的Java迭代器可能会引发ConcurrentModifcationException在底层集合迭代过程中被修改。故障安全作为发生在实例中的一个副本迭代是不会抛出任何异常的。快速失败的故障安全范例定义了当遭遇故障时系统是如何反应的。例如,用于失败的快速迭代器ArrayList和用于故障安全的迭代器ConcurrentHashMap

103、什么时候使用ConcurrentHashMap

ConcurrentHashMap被作为故障安全迭代器的一个实例,它允许完整的并发检索和更新。当有大量的并发更新时,ConcurrentHashMap此时可以被使用。这非常类似于Hashtable,但ConcurrentHashMap不锁定整个表来提供并发,所以从这点上ConcurrentHashMap的性能似乎更好一些。所以当有大量更新时ConcurrentHashMap应该被使用。

104Java BlockingQueue是什么?

Java BlockingQueue是一个并发集合util包的一部分。BlockingQueue队列是一种支持操作,它等待元素变得可用时来检索,同样等待空间可用时来存储元素。

105、哪一个List实现了最快插入?

 LinkedListArrayList是另个不同变量列表的实现。ArrayList的优势在于动态的增长数组,非常适合初始时总长度未知的情况下使用。LinkedList的优势在于在中间位置插入和删除操作,速度是最快的。

LinkedList实现了List接口,允许null元素。此外LinkedList提供额外的getremoveinsert方法在LinkedList的首部或尾部。这些操作使LinkedList可被用作堆栈(stack),队列(queue)或双向队列(deque)。

ArrayList实现了可变大小的数组。它允许所有元素,包括null 每个ArrayList实例都有一个容量(Capacity),即用于存储元素的数组的大小。这个容量可随着不断添加新元素而自动增加,但是增长算法并没有定义。当需要插入大量元素时,在插入前可以调用ensureCapacity方法来增加ArrayList的容量以提高插入效率。

106、什么是ArrayMap?它和HashMap有什么区别?

ArrayMapAndroid SDK中提供的,Android开发者可以略过. ArrayMap是用两个数组来模拟map,更少的内存占用空间,更高的效率.

106HashSetTreeSet的比较

1.TreeSet 是二叉树实现,Treeset中的数据是自动排序,不允许放入null

2.HashSet 是哈希表实现的,HashSet中的数据是无序的,可以放入null,但只能放入一个null,两者中的值都不能重复,就如数据库中唯一约束

3.HashSet要求放入的对象必须实现HashCode()方法,放入的对象,是以hashcode码作为标识的,而具有相同内容的String对象,hashcode是一样,所以放入的内容不能重复。但是同一个类的对象可以放入不同的实例。

适用场景分析:

HashSet是基于Hash算法实现的,其性能通常都优于TreeSet。我们通常都应该使用HashSet,在我们需要排序的功能时,我们才使用TreeSet

106HashMapConcurrentHashMap的区别

1HashMap不是线程安全的,而ConcurrentHashMap是线程安全的。

2ConcurrentHashMap采用锁分段技术,将整个Hash桶进行了分段segment,也就是将这个大的数组分成了几个小的片段segment,而且每个小的片段segment上面都有锁存在,那么在插入元素的时候就需要先找到应该插入到哪一个片段segment,然后再在这个片段上面进行插入,而且这里还需要获取segment锁。

3ConcurrentHashMap让锁的粒度更精细一些,并发性能更好。

107IdentityHashMapHashMap的区别

IdentityHashMapMap接口的实现。不同于

HashMap的,这里采用参考平等。

HashMap中如果两个元素是相等的,则key1.equals(key2)

IdentityHashMap中如果两个元素是相等的,则key1 == key2

108、集合为什么不直接实例化接口

Set set =new HashSet()     而不是Set set = new Set()  

Map map = new HashMap() 而不是HashMap map = new HashMap()

List list = new ArrayList()   而不是ArrayList list = new ArrayList();

1.Set,List,map是接口,不能实例化,只能实例化接口实现类,HashSet,ArrayList,HashMap

2.实现类中的属性和方法set,map,list不能调用,只能调用接口本身属性和方法

3.接口有多个实现类,便于代码的重构,以后只需改实现类,其他可不变

109、集合转数组

List list = new ArrayList();  String[] str =  (String[]) list.toArray(new String[list.size()])

110、数组转集合

String [] str = {"1","1","1","1"};   List list = Arrays.asList(str);

111Collection  Collections的区别。

Collection是集合类的上级接口,继承与他的接口主要有SetList.

Collections是针对集合类的一个帮助类,他提供一系列静态方法实现对各种集合的搜索、排序、线程安全化等操作。

java.util.Collection 是一个集合接口,它提供了对集合对象进行基本操作的通用接口方法,在 Java 类库中有很多具体的实现,意义是为各种具体的集合提供最大化的统一操作方式。 譬如 Collection 的实现类有 List、Set 等,List 的实现类有 LinkedList、ArrayList、Vector 等,Vector 的实现类有 Stack 等,不过切记 Map 是自立门户的,其提供了转换为 Collection 的方法,但是自己不是 Collection 的子类。

java.util.Collections 是一个包装类,它包含有各种有关集合操作的静态多态方法,此类构造 private 不能实例化,就像一个工具类,服务于 Java 的 Collection 框架,其提供的方法大概可以分为对容器接口对象进行操作类(查找和替换、排序和调整顺序、添加和修改)和返回一个容器接口对象类(适配器将其他类型的数据转换为容器接口对象、装饰器修饰一个给定容器接口对象增加某种性质)。

113、Set里的元素是不能重复的,那么用什么方法来区分重复与否呢? 是用==还是equals()? 它们有何区别?

Set里的元素是不能重复的,重复的元素将不会加到里面。通过Iterator()方法来区分是否重复,iterator()返回set中元素的迭代器,具体的set实现类依赖添加对象的equals()方法来检查等同性。元素重复与否是使用equals()方法进行判断的。

equals()==方法决定引用值是否指向同一对象equals()在类中被覆盖,为的是当两个分离的对象的内容和类型相配的话,返回真值。

114、什么是 Queue 以及 PriorityQueue LinkedList 的区别及特点?

首先 Queue 是一种模拟 FIFO 队列的数据结构,新元素插入(offer)到队列的尾部,访问元素(poll)返回队列头部,一般队列不允许随机访问队列中的元素。Queue 接口主要定义了如下几个方法:

  1. //将指定元素加入队列尾部
  2. void add(Object e);
  3. //获取队列头部元素,但是不删除该元素,如果队列为空抛出 NoSuchElementException 异常
  4. Object element();
  5. //将指定元素加入队列尾部(当使用有容量限制的队列时此方法比 add(Object e) 更好)
  6. boolean offer(Object e);
  7. //获取队列头部元素,但是不删除该元素,如果队列为空返回 null
  8. Object peek();
  9. //获取队列头部元素并删除该元素,如果队列为空则返回 null
  10. Object poll();
  11. //获取队列头部元素并删除该元素,如果队列为空抛出 NoSuchElementException 异常
  12. Object remove();

LinkedList 是一个比较奇怪的类,其即实现了 List 接口又实现了 Deque 接口(Deque Queue 的子接口),而 LinkedList 的实现是基于双向链表结构的,其容量没有限制,是非并发安全的队列,所以不仅可以当成列表使用,还可以当做双向队列使用,同时也可以当成栈使用(因为还实现了 pop push 方法)。此外 LinkedList 的元素可以为 null 值。

PriorityQueue 是一个优先级列表队列,因为 PriorityQueue 保存队列元素的顺序并不是按加入队列的顺序,而是按队列元素的大小进行重新排序,所以当调用 peek 或者 pull 方法从队列头取元素时并不是取出最先进入队列的元素,而是取出队列中最小的元素(默认顺序),所以说 PriorityQueue 实质违反了 FIFO 队列的基本原则,从而成了优先级列表实现,同时 PriorityQueue 的实现是基于动态扩容数组的二叉树堆结构,其最大容量长度为 Int 大小,是非并发安全的队列。此外 PriorityQueue 的元素不可为 null 值。

115PriorityQueue 是怎么确定哪一个元素的优先级最高的?

PriorityQueue 确定最高优先级元素使用的是堆数据结构,因为堆是一棵完全树,堆中某个节点的值总是不大于或不小于其父节点值的,常见的堆有二叉堆、斐波那契堆等,二叉堆是完全二叉树或者是近似完全二叉树的一种特殊堆,其分为最大堆和最小堆,最大堆中父结点值总是大于或等于任何一个子节点值,最小堆中父结点值总是小于或等于任何一个子节点值,由于二叉堆一直是自左向右自上向下一层层填充的,所以其可以用数组来表示而不是用链表,PriorityQueue 就是采用了基于动态数组的二叉堆来确定优先级。

116、简单说说 ArrayDeque LinkedList 的适用场景?

ArrayDeque LinkedList 都实现了 Deque 接口,如果只需要 Deque 接口且从两端进行操作则一般来说 ArrayDeque 效率更高一些,如果同时需要根据索引位置进行操作或经常需要在中间进行插入和删除操作则应该优先选 LinkedList 效率高些,因为 ArrayDeque 实现是循环数组结构(即一个动态扩容数组,默认容量 16,然后通过一个 head tail 索引记录首尾相连),而 LinkedList 是基于双向链表结构的。

117LinkedHashMapPriorityQueue的区别

PriorityQueue 是一个优先级队列,保证最高或者最低优先级的的元素总是在队列头部,但是 LinkedHashMap 维持的顺序是元素插入的顺序。当遍历一个 PriorityQueue 时,没有任何顺序保证,但是 LinkedHashMap 课保证遍历顺序是元素插入的顺序。

118WeakHashMapHashMap的区别是什么?

WeakHashMap 的工作与正常的 HashMap 类似,但是使用弱引用作为 key,意思就是当 key 对象没有任何引用时,key/value 将会被回收。

120ArrayListHashMap默认大小?

Java 7 中,ArrayList 的默认大小是 10 个元素,HashMap 的默认大小是16个元素(必须是2的幂)。这就是 Java 7 ArrayList HashMap 类的代码片段

private static final int DEFAULT_CAPACITY = 10;
 //from HashMap.java JDK 7
 static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16

79、简单说说 Comparable Comparator 的区别和场景?

Comparable 对实现它的每个类的对象进行整体排序,这个接口需要类本身去实现,若一个类实现了 Comparable 接口,实现 Comparable 接口的类的对象的 List 列表(或数组)可以通过 Collections.sort(或 Arrays.sort)进行排序,此外实现 Comparable 接口的类的对象可以用作有序映射(如TreeMap)中的键或有序集合(如TreeSet)中的元素而不需要指定比较器,实现 Comparable 接口必须修改自身的类(即在自身类中实现接口中相应的方法),如果我们使用的类无法修改(如 SDK 中一个没有实现 Comparable 的类),我们又想排序,就得用到 Comparator 这个接口了(策略模式)。所以如果你正在编写一个值类,它具有非常明显的内在排序关系,比如按字母顺序、按数值顺序或者按年代顺序,那你就应该坚决考虑实现 Comparable 这个接口, 若一个类实现了 Comparable 接口就意味着该类支持排序,而 Comparator 是比较器,我们若需要控制某个类的次序,可以建立一个该类的比较器来进行排序。 Comparable 比较固定,和一个具体类相绑定,而 Comparator 比较灵活,可以被用于各个需要比较功能的类使用,所以尽量推荐使用 Comparator 而不是 Comparable,因为这样可以保证单一职责原则。

 

121ComparatorComparable的区别?

Comparable 接口用于定义对象的自然顺序,而 comparator 通常用于定义用户定制的顺序。Comparable 总是只有一个,但是可以有多个 comparator 来定义对象的顺序。

122linkhashmaphashmap的区别

  1. HashMap是一个最常用的Map,它根据键的hashCode值存储数据,根据键可以直接获取它的值,具有很快的访问速度。HashMap最多只允许一条记录的键为NULL,允许多条记录的值为NULL
  2. HashMap不支持线程同步,即任一时刻可以有多个线程同时写HashMap,可能会导致数据的不一致性。如果需要同步,可以用CollectionssynchronizedMap方法使HashMap具有同步的能力。
  3. HashtableHashMap类似,不同的是:它不允许记录的键或者值为空;它支持线程的同步,即任一时刻只有一个线程能写Hashtable,因此也导致了Hashtable在写入时会比较慢。
  4. LinkedHashMap保存了记录的插入顺序,在用Iterator遍历LinkedHashMap时,先得到的记录肯定是先插入的。

123map的实现类

HashMap                Hashtable      Properties      LinkedHashMap         IdentityHashMap

TreeMap                WeakHashMap     ConcurrentHashMap

124list删除元素   调用remove或者removeall方法

125、如何实现集合排序?

你可以使用有序集合,如 TreeSet TreeMap,你也可以使用有顺序的的集合,如 list,然后通过 Collections.sort() 来排序。

126、如何去遍历一个Map集合

keySet()    values()    entrySet()  

Map.Entry : getKey() getValue()

127、把一个集合的数据拷贝到另一个集合的方法。

1、通用的就是循环添加

2、addall()或者add等接口直接把一个list添加到另一个list,比如java就有addall方法

128、如何打印数组内容

你可以使用 Arrays.toString() Arrays.deepToString() 方法来打印数组。由于数组没有实现 toString() 方法,所以如果将数组传递给 System.out.println() 方法,将无法打印出数组的内容,但是 Arrays.toString() 可以打印每个元素。

129TreeMap是实现原理  采用红黑树实现

130、遍历ArrayList时如何正确移除一个元素

该问题的关键在于面试者使用的是 ArrayList remove() 还是 Iterator remove()方法。这有一段示例代码,是使用正确的方式来实现在遍历的过程中移除元素,而不会出现 ConcurrentModificationException 异常的示例代码。

131、你了解Fail-Fast机制吗  常说的快速失败

  1. 泛型好处?

1.类型安全2.消除强制类型转换3.减少装箱拆箱,提高性能,减少出错。在编译时检查类型安全,并且所有的强制转换都是自动和隐式的,提高代码重用率。

泛型类型参数不能用在Java异常处理catch语句中。泛型类型擦除,Jvm无法区别异常。

需要泛型之间的类型转换怎么做?通配符?与PECS

  1. 做过上传吗,说说注意事项。

上传文件中文乱码2.设置解析器缓冲区的大小,以及临时文件的删除3.限制上传文件类型及大小

  1. 如何取得当前时间?

java.text.SimpleDateFormat

   SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

   String ok = sdf.format(System.currentTimeMillis());

   System.out.println(ok);

java.util.Date

   Date now = new Date();

   System.out.println(now);

   System.out.println(now.getYear()+1900);

   System.out.println(now.getMonth() + 1);

   System.out.println(now.getDate());

   System.out.println(now.getHours());

   System.out.println(now.getMinutes());

   System.out.println(now.getSeconds());

java.util.Calendar

   Calendar now = Calendar.getInstance();

   System.out.println(now.get(1));   System.out.println(now.get(2)+1);

   System.out.println(now.get(5));   System.out.println(now.get(11));

   System.out.println(now.get(12));  System.out.println(now.get(13));

  1. timestampdate区别

DATE只保存日期,不保存时分秒

DATETIME类型用在你需要同时包含日期和时间信息的值时。MySQL检索并且以'YYYY-MM-DD HH:MM:SS'格式显示DATETIME值,支持的范围是'1000-01-01 00:00:00'到'9999-12-31 23:59:59'。

TIMESTAMP列类型提供一种类型,你可以使用它自动地用当前的日期和时间标记INSERT或UPDATE的操作。如果你有多个TIMESTAMP列,只有第一个自动更新。

136SimpleDateFormat是线程安全的吗?

DateFormat 的所有实现,包括 SimpleDateFormat 都不是线程安全的,因此你不应该在多线程序中使用,除非是在对外线程安全的环境中使用,如 SimpleDateFormat 限制在 ThreadLocal 中。如果你不这么做,在解析或者格式化日期的时候,可能会获取到一个不正确的结果。因此,从日期、时间处理的所有实践来说,我强力推荐 joda-time 库。

137、如何格式化日期?

Java 中,可以使用 SimpleDateFormat 类或者 joda-time 库来格式日期。DateFormat 类允许你使用多种流行的格式来格式化日期。参见答案中的示例代码,代码中演示了将日期格式化成不同的格式,如 dd-MM-yyyy ddMMyyyy

138POI是做什么用的,请具体写其中涉及到的一个类?

解析Excel, Workbook-->XSSFWorkbook  HSSFWorkbook

139JSONObject是哪个包下的   net.sf.json.JSONObject

144、如果我同时发送多个ajax,多个异步或是多个同步,会出现什么问题。

  发送多个同步请求效率会慢,必须等待上一个结束才能执行下一个

  发送多个同步请求则可能会导致返回的结果混乱

140、请写一个校验数据格式为 10-500 的正则表达式  ([1-9]\d)|([1-4]\d{2})|(500)

141、原生ajax请求的五个步骤

第一步,创建XMLHttpRequest,第二步,注册回调函数 第三步,配置请求信息

第四步,发送数据,与服务器开始交互

第五步,创建回调函数, 接受服务器返回数据。

142AJAX是什么? 描述ajax的原理

AJAX = Asynchronous JavaScript and XML(异步 JavaScript 和 XML),又叫异步刷新

Ajax 的原理简单来说通过 XmlHttpRequest 对象来向服务器发异步请求,从服务器获得数据,然后用 Javascript 来操作 DOM 而更新页面。这其中最关键的一步就是从服务器获得请求数据。

XmlHttpRequest 是 ajax 的核心机制,它是在 IE5 中首先引入的,是一种支持异步请求的技术。简单的说,也就是 Javascript 可以及时向服务器提出请求和处理响应,而不阻塞用户。达到无刷新的效果。

143ajax怎么实现跨域访问并且是安全的?

http:// www . google : 8080 / script/jquery.js

  http:// (协议号)www  (子域名)    google (主域名)

          8080 (端口号)    script/jquery.js (请求的地址)

* 当协议、子域名、主域名、端口号中任意一各不相同时,都算不同的“域”。

* 不同的域之间相互请求资源,就叫“跨域”。

处理跨域的方法:1 -- 代理。2 -- JSONPJSONP只支持 “GET” 请求,但不支持 “POST” 请求。3 -- XHR2(推荐方法).“XHR2”全称“XMLHttpRequest Level2”是HTML5提供的方法,对跨域访问提供了很好的支持.

145、怎么样在一个方法里面这两个ajax,其中第二个ajax,需要用到第一个的传值,可不可以两个挨着写

不能,即便挨着写也是两个不同的异步请求,很可能第二个ajax在发出请求的时候第一个ajax的值还没有传回来 同步两个请求

146、同步ajax跟异步ajax有什么不同,那个好用?

     request.open(method,url,async,username,password);

     async:true为异步

     false为同步

    异步方式客户端不需要等待服务器的响应。同步方式客户端必须等待服务器响应之后才可以继续执行后续操作。要根据实际情况选择方式,异步效率高但是对服务器造成更高的负载,当某些页面可能会发出多个请求,甚至是有组织的有计划的有队形的高强度的request时,后一个是会覆盖前一个的,则应该使用同步. 

147、什么是反射?请用反射动态创建一个类的对象(写关键代码,其它可省略)

在运行状态中对于任意一个类,都能知道这个类的所有属性和方法,对于任意一个对象都能调用他的任意一个方法和属性。这种动态获取信息以及调用对象方法的功能叫Java语言反射机制。JAVA语言编译之后会生成一个.class文件,反射就是通过字节码文件找到某一个类、类中的方法以及属性等。

反射,程序运行时动态获取类型信息,完成对象创建,方法调用等。例如:

Class myclass=Class.forNama("包名.类名");

Student stu=Factory.createInstance("stu1");

148class.forname的作用

Class.forName(xxx.xx.xx)返回的是一个类。.newInstance()后才创建一个对象。

Class.forName(xxx.xx.xx)的作用是要求JVM查找并加载指定的类,也就是说JVM会执行该类的静态代码段

149class.forname应用情景

情景一:加载数据库驱动的时候  情景二:使用AIDL与电话管理Servic进行通信

150、在初始化一个类,生成一个实例的时候,newInstance()new关键字区别?

  1. newInstance()是一个方法,new是关键字。
  2. newInstance()是使用类加载机制,new创建一个新类。
  3. newInstance: 弱类型。低效率。只能调用无参构造。  

new: 强类型。相对高效。能调用任何public构造。

  1. 这主要考虑到软件的可伸缩、可扩展和可重用等软件设计思想。

151Class类的常用方法  

1getName() 

一个Class对象描述了一个特定类的属性,Class类中最常用的方法getName String 的形式返回此 Class 对象所表示的实体(类、接口、数组类、基本类型或 void)名称。

2newInstance()

Class还有一个有用的方法可以为类创建一个实例,这个方法叫做newInstance()。例如:
    x.getClass.newInstance(),创建了一个同x一样类型的新实例。newInstance()方法调用默认构造器(无参数构造器)初始化新建对象。

3getClassLoader() 返回该类的类加载器。

4getComponentType() 返回表示数组组件类型的 Class

5getSuperclass() 返回表示此 Class 所表示的实体(类、接口、基本类型或 void)的超类的 Class

6isArray() 判定此 Class 对象是否表示一个数组类。

152、任务调度?

任务调度:是指基于给定时间点,给定时间间隔或者给定执行次数自动执行任务。

四种任务调度的 Java 实现:

Timer, ScheduledExecutor,开源工具包 Quartz,开源工具包 JCronTab

152、说一说你在项目中是如何使用任务调度的?

使用spring内置的quartz组件实现任务调度

quartz调度任务的流程 :

        1. 提供任务对象   2. ioc容器中配置任务对象

        3. 描述任务细节 JobDetail

        4. 为任务设置触发器  Trigger 设置触发时间(通过cron表达式)

        5. 配置总调度类 Scheduler

153、项目中数据库连接池怎么配置的,说说各个参数的含义。

基本配置:是指连接池进行数据库连接的

四个基本必需配置:传递给JDBC驱动用于连接数据库用户名、密码、URL以及驱动类名。

关键配置:

最小连接数:是数据库一直保持的数据库连接数。

初始化连接数:连接池启动时创建的初始化数据库连接数量。

最大连接数:是连接池能申请的最大连接数,如果数据库连接请求超过此数,后面的数据库连接请求被加入到等待队列中。

最大等待时间:当没有可用连接时,连接池等待连接被归还的最大时间,超过时间则抛出异常,可设置参数为0或者负数使得无限等待(根据不同连接池配置)。

154httpwebservice请求的区别

这两个是完全不同的概念,不存在区别,http是一种网络协议,而webservice是一种两个应用程序之间实现通信的解决方案。

但是两者之间是有联系的Webservice实现消息的传送就是将消息依附在http上进行传输的。

155、工程中怎么开启事物的

事务的开启方式依赖于工程中使用的事务形式

编程式事务(JDBC事务)  jdbc事务是绑定在connection中的  connection.setAutoCommit(true/false)

声明式事务(spring aop事务)   ioc容器中配置事务通知bean   以切入点的方式在需要开启事务的方法中引用该通知

156、两个工程之间怎么关联 (当时我就直接说配置webservice,没说别的)

配置webservice

<servlet>

  <servlet-name>cxf</servlet-name>

  <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>

 </servlet>

 <servlet-mapping>

  <servlet-name>cxf</servlet-name>

  <url-pattern>/ws/*</url-pattern>

 </servlet-mapping>

157、解析xml

  1. 获得解析器对象2.获得文件document3.获得根元素4.获得一级子元素5.遍历

158302是啥意思 404500的区别

302是代表暂时性转移,也就是在服务器端发生的跳转,和forward有点类似,但它们是俩种东西,只是原理类似,这种方式较容易发生一个问题,容易发生url劫持。

159、项目中如果遇到系统问题(如系统过载)怎么处理?

系统过载 - 处理方式 : 过载保护 - 使用线程池

A 当一个请求过来,线程池开启一个线程来处理,直到线程池中所有的线程都在处理请求

B 当线程池中没有空闲线程了,就将请求添加到有界队列当中,直到队列满为止

C 当队列满以后,在开启线程来处理新的请求,直到开启的线程数达到某个临界值(这个临界值可以根据当前系统的承载能力来定)

D 当开启的线程数达到临界后,任务队列又已经满了后,此时再过来的请求将被拒绝,被拒绝的请求在本地系列化,将保存的数据同步到离线数据系统进行处理

160、项目中流行的工作流引擎 

1JBPM 2Activiti 3Shark 4osworkflow

160、文件上传下载?

        使用SmartUpload

        //使用SmartUpload插件进行文件的上传

                     //1:引入SmartUpload

                     SmartUpload su = new SmartUpload();

                     //2:设置允许上传文件的后缀名

                     su.setAllowedFilesList("jpg,jpeg,gif,bmp");

                     //3:设置允许上传文件的总大小 这里设置的是6m

                     su.setTotalMaxFileSize(6*1024*1024);

                     //4:初始化

                     su.initialize(this.getServletConfig(),request,response);

                     //5:上传

                     su.upload();

                     //设置一个路径,将文件最终保存在此路径下

                     //可以使用绝对路径,也可以使用相对路径

                     //因为目前的定位就在服务器端,所以使用相对路径直接在服务器选取

                     //拿取所有上传的文件

                     Files files = su.getFiles();

                     //拿取唯一上传文件

                     File file = files.getFile(0);

                     //拿取上传文件的全名

                     String fileName = file.getFileName();

                     //组合一个要上传的路径

                     String path = "/image/"+fileName;

                     //另存到此路径

                     file.saveAs(path);

        使用SmartUpload下载:

             SmartUpload su = new SmartUpload();

                     //设置保存的地点,注意填写null由浏览器提示保存地址

                     su.setContentDisposition(null);

                     su.initialize(this.getServletConfig(), request,response);

                     su.downloadFile(路径);

XML部分

1xml有哪些解析技术?区别是什么?

DOM,SAX,STAX

DOM:处理大型文件时其性能下降的非常厉害。这个问题是由DOM的树结构所造成的,这种结构占用的内存较多,而且DOM必须在解析文件之前把整个文档装入内存,适合对XML的随机访问SAX:不现于DOM,SAX是事件驱动型的XML解析方式。它顺序读取XML文件,不需要一次全部装载整个文件。当遇到像文件开头,文档结束,或者标签开头与标签结束时,它会触发一个事件,用户通过在其回调事件中写入处理代码来处理XML文件,适合对XML的顺序访问

STAX:Streaming APIfor XML (StAX)

2、你在项目中用到了xml技术的哪些方面?如何实现的?

用到了数据存贮,信息配置两方面。在做数据交换平台时,将不能数据源的数据组装成XML文件,然后将XML文件压缩打包加密后通过网络传送给接收者,接收解密与解压缩后再同XML文件中还原相关信息进行处理。在做软件配置时,利用XML可以很方便的进行,软件的各种配置参数都存贮在XML文件中。

3XML文档定义有几种形式?它们之间有何本质区别?解析XML文档有哪几种方式?

a: 两种形式dtd  schema

b: 本质区别:schema本身是xml的,可以被XML解析器解析(这也是从DTD上发展schema的根本目的)

c:DOM,SAX,STAX

DOM:处理大型文件时其性能下降的非常厉害。这个问题是由DOM的树结构所造成的,这种结构占用的内存较多,而且DOM必须在解析文件之前把整个文档装入内存,适合对XML的随机访问

SAX:不现于DOM,SAX是事件驱动型的XML解析方式。它顺序读取XML文件,不需要一次全部装载整个文件。当遇到像文件开头,文档结束,或者标签开头与标签结束时,它会触发一个事件,用户通过在其回调事件中写入处理代码来处理XML文件,适合对XML的顺序访问

STAX:Streaming API for XML (StAX)

4、深拷贝和浅拷贝的区别是什么?

1).浅拷贝:被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象。

换言之,浅拷贝仅仅复制所考虑的对象,而不复制它所引用的对象。

2).深拷贝:被复制对象的所有变量都含有与原来的对象相同的值,而那些引用其他对象的变量将指向被复制过的新对象,而不再是原有的那些被引用的对象。

换言之,深拷贝把要复制的对象所引用的对象都复制了一遍。

5、黑盒测试、灰盒测试、白盒测试、单元测试有什么区别?

黑盒测试关注程序的功能是否正确,面向实际用户;

白盒测试关注程序源代码的内部逻辑结构是否正确,面向编程人员;

灰盒测试是介于白盒测试与黑盒测试之间的一种测试。

单元测试(Unit Testing)是对软件基本组成单元进行的测试,如函数或是一个类的方法。这里的单元,就是软件设计的最小单位。

6、你所知道网络协议有那些?

HTTP:超文本传输协议
FTP:文件传输协议
SMPT:简单邮件协议
TELNET:远程终端协议
POP3:邮件读取协议

7maven的使用

Maven是一个项目管理工具(maven里面有很多jar,用到时自动导入jar)

包含了:项目对象模型,标准集合,项目生命周期,依赖管理系统和用来运行定义在生命周期阶段中插件目标的逻辑

Maven冲突原则:

1.短路优先  A-B -C-X(jar)  A-D-X(jar)   第二条将优先

2.路径相同的情况  先声明先优先,先解析谁

8、如何设定的weblogic的热启动模式(开发模式)与产品发布模式?

可以在管理控制台中修改对应服务器的启动模式为开发或产品模式之一。或者修改服务的启动文件或者commenv文件,增加setPRODUCTION_MODE=true

9、如何启动时不需输入用户名与密码?

修改服务启动文件,增加 WLS_USERWLS_PW项。也可以在boot.properties文件中增加加密过的用户名和密码.

10、在weblogic管理制台中对一个应用域(或者说是一个网站,Domain)进行jmsejb或连接池等相关信息进行配置后,实际保存在什么文件中?

保存在此Domainconfig.xml文件中,它是服务器的核心配置文件。

11、说说weblogic中一个Domain的缺省目录结构?比如要将一个简单的helloWorld.jsp放入何目录下,然的在浏览器上就可打入http://主机:端口号//helloword.jsp就可以看到运行结果了又比如这其中用到了一个自己写的javaBean该如何办?

Domain目录服务器目录applications,将应用目录放在此目录下将可以作为应用访问,如果是Web应用,应用目录需要满足Web应用目录要求,jsp文件可以直接放在应用目录中,Javabean需要放在应用目录的WEB-INF目录的classes目录中,设置服务器的缺省应用将可以实现在浏览器上无需输入应用名。

12、在weblogic中发布ejb需涉及到哪些配置文件

不同类型的EJB涉及的配置文件不同,都涉及到的配置文件包括ejb-jar.xml,weblogic-ejb-jar.xmlCMP实体Bean一般还需要weblogic-cmp-rdbms-jar.xml

13、如何在weblogic中进行ssl配置与客户端的认证配置或说说j2ee(标准)进行ssl的配置?

缺省安装中使用DemoIdentity.jksDemoTrust.jks  KeyStore实现SSL,需要配置服务器使用Enable SSL,配置其端口,在产品模式下需要从CA获取私有密钥和数字证书,创建identitytrustkeystore,装载获得的密钥和数字证书。可以配置此SSL连接是单向还是双向的。

 webservice部分

1WEB SERVICE名词解释。JSWDL开发包的介绍。JAXPJAXM的解释。SOAPUDDI,WSDL解释。

webservice是一种跨编程语言和跨操作系统的远程调用技术,遵循SOPA/WSDL规范。

Web Service是基于网络的、分布式的模块化组件,它执行特定的任务,遵守具体的技术规范,这些规范使得Web Service能与其他兼容的组件进行互操作。

JAXP(Java API forXML Parsing) 定义了在Java中使用DOM, SAX, XSLT的通用的接口。这样在你的程序中你只要使用这些通用的接口,当你需要改变具体的实现时候也不需要修改代码。

JAXM(Java API forXML Messaging) 是为SOAP通信提供访问方法和传输机制的API

WSDL是一种XML 格式,用于将网络服务描述为一组端点,这些端点对包含面向文档信息或面向过程信息的消息进行操作。这种格式首先对操作和消息进行抽象描述,然后将其绑定到具体的网络协议和消息格式上以定义端点。相关的具体端点即组合成为抽象端点(服务)。

SOAP即简单对象访问协议(Simple Object Access Protocol),它是用于交换XML编码信息的轻量级协议。

UDDI 的目的是为电子商务建立标准;UDDI是一套基于Web的、分布式的、为WebService提供的、信息注册中心的实现标准规范,同时也包含一组使企业能将自身提供的Web Service注册,以使别的企业能够发现的访问协议的实现标准。

2CORBA是什么?用途是什么?

CORBA 标准是公共对象请求代理结构(Common Object Request Broker Architecture),由对象管理组织 (Object Management Group,缩写为 OMG)标准化。它的组成是接口定义语言(IDL), 语言绑定(binding:也译为联编)和允许应用程序间互操作的协议。其目的为:用不同的程序设计语言书写在不同的进程中运行,为不同的操作系统开发。

3webservice的特性。缺点:

1、可操作的的分布式应用程序

2、普遍性、使用HTTP和XML进行通信

3、Web Service 甚至可以穿越防火墙,真正的自由通信

4、通过 SOAP 协议实现异地调用

缺点一:单机应用程序 缺点二:局域网的同构应用程序

4、如何查看在weblogic中已经发布的EJB?

可以使用管理控制台,在它的Deployment中可以查看所有已发布的EJB

5GITSVN的区别

1、GIT是分布式的,SVN不是。

2、GIT把内容按元数据方式存储,而SVN是按文件。

3、GIT分支和SVN的分支不同。

4、GIT没有一个全局的版本号,而SVN有。

5、GIT的内容完整性要优于SVN。

EBJ部分

1EJB是基于哪些技术实现的?并说出SessionBeanEntityBean的区别,StatefulBeanStatelessBean的区别。

EJB包括Session BeanEntityBeanMessage Driven Bean,基于JNDIRMIJAT等技术实现。

SessionBeanJ2EE应用程序中被用来完成一些服务器端的业务操作,例如访问数据库、调用其他EJB组件。EntityBean被用来代表应用系统中用到的数据。

对于客户机,SessionBean是一种非持久性对象,它实现某些在服务器上运行的业务逻辑。

对于客户机,EntityBean是一种持久性对象,它代表一个存储在持久性存储器中的实体的对象视图,或是一个由现有企业应用程序实现的实体。

Session Bean 还可以再细分为 Stateful Session Bean  StatelessSession Bean ,这两种的 Session Bean都可以将系统逻辑放在method之中执行,不同的是 Stateful Session Bean 可以记录呼叫者的状态,因此通常来说,一个使用者会有一个相对应的 Stateful Session Bean 的实体。StatelessSession Bean 虽然也是逻辑组件,但是他却不负责记录使用者状态,也就是说当使用者呼叫Stateless Session Bean 的时候,EJBContainer 并不会找寻特定的 Stateless Session Bean 的实体来执行这个 method。换言之,很可能数个使用者在执行某个 Stateless Session Bean methods 时,会是同一个 Bean  Instance 在执行。从内存方面来看,Stateful Session Bean  StatelessSession Bean 比较, Stateful Session Bean 会消耗J2EE Server 较多的内存,然而 Stateful Session Bean 优势却在于他可以维持使用者的状态。

2、简要讲一下 EJB  7  Transaction Level?

3EJBJAVA BEAN的区别?

Java Bean 是可复用的组件,对Java Bean并没有严格的规范,理论上讲,任何一个Java类都可以是一个Bean。但通常情况下,由于JavaBean是被容器所创建(如Tomcat)的,所以Java Bean应具有一个无参的构造器,另外,通常Java Bean还要实现Serializable接口用于实现Bean的持久性。Java Bean实际上相当于微软COM模型中的本地进程内COM组件,它是不能被跨进程访问的。Enterprise Java Bean 相当于DCOM,即分布式组件。它是基于Java的远程方法调用(RMI)技术的,所以EJB可以被远程访问(跨进程、跨计算机)。但EJB必须被布署在诸如WebspereWebLogic这样的容器中,EJB客户从不直接访问真正的EJB组件,而是通过其容器访问。EJB容器是EJB组件的代理,EJB组件由容器所创建和管理。客户通过容器来访问真正的EJB组件。

4EJB包括(SessionBean,EntityBean)说出他们的生命周期,及如何管理事务?

SessionBeanStatelessSession Bean 的生命周期是由容器决定的,当客户机发出请求要建立一个Bean的实例时,EJB容器不一定要创建一个新的Bean的实例供客户机调用,而是随便找一个现有的实例提供给客户机。当客户机第一次调用一个Stateful Session Bean 时,容器必须立即在服务器中创建一个新的Bean实例,并关联到客户机上,以后此客户机调用Stateful Session Bean 的方法时容器会把调用分派到与此客户机相关联的Bean实例。

EntityBeanEntityBeans能存活相对较长的时间,并且状态是持续的。只要数据库中的数据存在,Entity beans就一直存活。而不是按照应用程序或者服务进程来说的。即使EJB容器崩溃了,Entity beans也是存活的。Entity Beans生命周期能够被容器或者 Beans自己管理。

EJB通过以下技术管理实务:对象管理组织(OMG)的对象实务服务(OTS),Sun MicrosystemsTransactionServiceJTS)、Java TransactionAPIJTA),开发组(X/Open)的XA接口。

5EJB容器提供的服务

主要提供声明周期管理、代码产生、持续性管理、安全、事务管理、锁和并发行管理等服务。

6EJB的激活机制

Stateful Session Bean 为例:其Cache大小决定了内存中可以同时存在的Bean实例的数量,根据MRUNRU算法,实例在激活和去激活状态之间迁移,激活机制是当客户端调用某个EJB实例业务方法时,如果对应EJBObject发现自己没有绑定对应的Bean实例则从其去激活Bean存储中(通过序列化机制存储实例)回复(激活)此实例。状态变迁前会调用对应的ejbActiveejbPassivate方法。

7EJB的几种类型

会话(SessionBean ,实体(EntityBean消息驱动的(Message DrivenBean

会话Bean又可分为有状态(Stateful)和无状态(Stateless)两种

实体Bean可分为Bean管理的持续性(BMP)和容器管理的持续性(CMP)两种

8、客服端调用EJB对象的几个基本步骤

设置JNDI服务工厂以及JNDI服务地址系统属性,查找Home接口,从Home接口调用Create方法创建Remote接口,通过Remote接口调用其业务方法。

EJB容器:Enterprisejava bean 容器。更具有行业领域特色。他提供给运行在其中的组件EJB各种管理功能。只要满足J2EE规范的EJB放入该容器,马上就会被容器进行高效率的管理。并且可以通过现成的接口来获得系统级别的服务。例如邮件服务、事务管理。

JNDI:(JavaNaming & Directory InterfaceJAVA命名目录服务。主要提供的功能是:提供一个目录系统,让其它各地的应用程序在其上面留下自己的索引,从而满足快速查找和定位分布式应用程序的功能。

JMS:(JavaMessage ServiceJAVA消息服务。主要实现各个应用程序之间的通讯。包括点对点和广播。

JTA:(JavaTransaction APIJAVA事务服务。提供各种分布式事务服务。应用程序只需调用其提供的接口即可。

JAF:(JavaAction FrameWorkJAVA安全认证框架。提供一些安全控制方面的框架。让开发者通过各种部署和自定义实现自己的个性安全控制策略。

RMI/IIOP:RemoteMethod Invocation /internet对象请求中介协议)他们主要用于通过远程调用服务。例如,远程有一台计算机上运行一个程序,它提供股票分析服务,我们可以在本地计算机上实现对其直接调用。当然这是要通过一定的规范才能在异构的系统之间进行通信。RMIJAVA特有的。

4. 面向对象六大原则

1.单一职责原则——SRP

让每个类只专心处理自己的方法。

2.开闭原则——OCP

软件中的对象(类,模块,函数等)应该对于扩展是开放的,但是对于修改是关闭的。

3.里式替换原则——LSP

子类可以去扩展父类,但是不能改变父类原有的功能。

4.依赖倒置原则——DIP

应该通过调用接口或抽象类(比较高层),而不是调用实现类(细节)

5.接口隔离原则——ISP

把接口分成满足依赖关系的最小接口,实现类中不能有不需要的方法。

6.迪米特原则——LOD

高内聚,低耦合。

 

9、请设计一个一百亿的计算器

首先要明白这道题目的考查点是什么,一是大家首先要对计算机原理的底层细节要清楚、要知道加减法的位运算原理和知道计算机中的算术运算会发生越界的情况,二是要具备一定的面向对象的设计思想。

首先,计算机中用固定数量的几个字节来存储的数值,所以计算机中能够表示的数值是有一定的范围的,为了便于讲解和理解,我们先以byte 类型的整数为例,它用1个字节进行存储,表示的最大数值范围为-128+127-1在内存中对应的二进制数据为11111111,如果两个-1相加,不考虑Java运算时的类型提升,运算后会产生进位,二进制结果为1,11111110,由于进位后超过了byte类型的存储空间,所以进位部分被舍弃,即最终的结果为11111110,也就是-2,这正好利用溢位的方式实现了负数的运算。-128在内存中对应的二进制数据为10000000,如果两个-128相加,不考虑Java运算时的类型提升,运算后会产生进位,二进制结果为1,00000000,由于进位后超过了byte类型的存储空间,所以进位部分被舍弃,即最终的结果为00000000,也就是0,这样的结果显然不是我们期望的,这说明计算机中的算术运算是会发生越界情况的,两个数值的运算结果不能超过计算机中的该类型的数值范围。由于Java中涉及表达式运算时的类型自动提升,我们无法用byte类型来做演示这种问题和现象的实验,大家可以用下面一个使用整数做实验的例子程序体验一下:

1  inta = Integer.MAX_VALUE;
3  intb = Integer.MAX_VALUE;
5  intsum = a + b;
7  System.out.println(“a=”+a+”,b=”+b+”,sum=”+sum);

先不考虑long类型,由于int的正数范围为231次方,表示的最大数值约等于2*1000*1000*1000,也就是20亿的大小,所以,要实现一个一百亿的计算器,我们得自己设计一个类可以用于表示很大的整数,并且提供了与另外一个整数进行加减乘除的功能,大概功能如下:

1)这个类内部有两个成员变量,一个表示符号,另一个用字节数组表示数值的二进制数

2)有一个构造方法,把一个包含有多位数值的字符串转换到内部的符号和字节数组中

3)提供加减乘除的功能

 1 public class BigInteger {
 2     int sign;
 3     byte[] val;
 5     public Biginteger(String val) {
 6          sign= ;
 7          val= ;
 8     }
10     public BigInteger add(BigInteger other) {
11     }
13     public BigInteger subtract(BigInteger other) {
14     }
16     public BigInteger multiply(BigInteger other) {
17     }
19     public BigInteger divide(BigInteger other) {
20     }
22 }

 

Set:集合,元素是无序的(因为没有索引),元素不可以重复。可以有null元素。
|--->HashSet(JDK1.2):底层数据结构是哈希表、存取速度快、元素唯一、线程不同步。
保证性元素唯一的原理:
先判断元素的hashCode值是否相同,再判断两元素的equals方法是否为true
(HashSet里面存的自定义元素要复写hashCodeequals方法,以保证元素的唯一性!)
|--->TreeSet:底层数据结构式二叉树。可以对Set集合中的元素进行排序。元素有序、线程不同步。

保证元素唯一性的依据:compareTo方法return 0
TreeSet排序的第一种方式:让元素自身具备比较性,比如八种基本数据类型或则字符串,
实现Compareble接口,覆盖compareTo方法,
此方式是元素的自然顺序
TreeSet排序的第一种方式:当元素自身不具备比较性(比如存储学生对象时)或者具备的
比较性不是我们所需要的比较性时(比如想字符串的长度排序),
此时就需要让集合自身具备自定义的比较性。 
那如何让集合自身具备比较性呢?可在集合初始化时,
就让集合具备比较方式。即定义一个类,
实现Comparator接口,覆盖compare方法。

HashSet是如何保证元素唯一性的呢?
**如果两元素的hashCode值不同,则不会调用equals方法
**如果两元素的hashCode值相同,则继续判断equals是否返回true
**hashCodeequals方法虽然定义在自定义对象类里面,但不是我们手动调用
而是往HashSet集合里面存储元素的时候,集合底层自己调用hashCodeequals
它自己拿对象去判断,自己判断两元素是否是同一个元素。

(2)TreeSet:
TreeSet
要求往里面存的元素具备比较性,否则会报错。
TreeSet排序的第一种方式:让元素自身具备比较性
定义对象类,实现Compareble接口,复写compareTo方法,此方式是元素的自然顺序

reeSet排序的第一种方式:让集合具备比较性
当元素自身不具备比较性(比如存储学生对象时)或者具备的
比较性不是我们所需要的比较性时(比如想字符串的长度排序),
此时就需要让集合自身具备自定义的比较性。 
那如何让集合自身具备比较性呢?可在集合初始化时,
就让集合具备比较方式。即定义一个类,
实现Comparator接口,覆盖compare方法。

基本数据类型或字符串对象均实现了Comparable接口,故同种类型基本数据间具备比较性,即自然顺序。
**Map:顶层接口,该集合存储的是键值对,而且键是唯一的,MapSet很像,Set集合底层就是使用了Map集合。
Map集合没有迭代器,要取出元素必须先将Map集合转换成Set集合才能遍历元素
|--->HashTable(JDK1.0): 
底层是哈希表数据结构;
不可以使用null键和null值;
用作键的对象必须实现hashCodeequals方法来保证键的唯一性
线程同步,效率低
|--->HashMap(JDK1.2):
底层是哈希表数据结构;
允许使用null键和null值;
线程不同步,效率高;
保证元素唯一性的:
原理:先判断元素的hashCode值是否相同,再判断两元素的equals方法是否为true
(HashSet里面存的自定义元素要复写hashCodeequals方法,
以保证元素的唯一性!)

Map集合没有迭代器,以下是Map的两种取出方式:
第一种:Set<K> keySet()
返回此映射中包含的键的Set视图,将Map集合中所有的键存入Set集合,然后再通过Set集合的
迭代器取出所有的键,再根据get方法获取每个键的值;
第二种:Set<Map.Entry<K,V>> entrySet() 
返回此映射中包含的映射关系的Set视图,将Map集合中的映射关系存入到Set集合中,
这个映射关系的数据类型是Map.entry,再通过Map.Entry类的方法再要取出关系里面的键和值

Map集合和Collection集合的区别?
1
Map中一次存储是键值对。
Collection中一次存储是单个元素。
2
Map的存储使用的put方法。
Collection存储使用的是add方法。 
3
Map集合没有迭代器,Map的取出,是将Map转成Set,在使用迭代器取出。
Collection取出,使用就是迭代器。
4
如果对象很多,必须使用集合存储。
如果元素存在着映射关系,可以优先考虑使用Map存储或者用数组,
如果没有映射关系,可以使用Collection存储。

堆栈和队列
堆栈:先进后出,比如杯子里的水
队列:先进先出,比如水管的水

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值