javainterview
- java语言特点有哪些?
1、面向对象:java同c++一样都是面向对象的,有面向对象的特点封装,继承,多态。
2、平台无关性: java是一次编译到处运行的语言,因此采用java语言编写的程序具有很好的可移植性,而保证这一点的正是java虚拟机机制
3、可靠性和安全性:
Java是一个强类型语言,它允许扩展编译时检查潜在类型不匹配问题的功能。
Java要求显式的方法声明,它不支持C风格的隐式声明。这些严格的要求保证编译程序能捕捉调用错误,这就导致更可靠的程序。
java的存储分配模型是它防御恶意代码的主要方法之一。Java没有指针,所以程序员不能得到隐蔽起来的内幕和伪造指针去指向存储器。
更重要的是,Java编译程序不处理存储安排决策,所以程序员不能通过查看声明去猜测类的实际存储安排。
编译的Java代码中的存储引用在运行时由Java解释程序决定实际存储地址。
4、 支持多线程:
c++没有内置的多线程机制,因此必须调用操作系统的多线程功能来进行多线程程序设计,而java却提供了多线程支持。
5、 支持网络编程并且很方便。java语言诞生本身就是为简化网络编程设计的。
6、 编译与解释并存:
一、你可以说它是编译型的。因为所有的Java代码都是要编译的,.java不经过编译就什么用都没有,无法生成.class文件也就是java字节码。
二、你可以说它是解释型的。因为java代码编译后不能直接运行,它是解释运行在JVM上的,所以它是解释运行的,那也就算是解释的了。
三、但是,现在的JVM为了效率,都有一些JIT优化。它又会把.class的二进制代码编译为本地的代码直接运行,所以,又是编译的。
- java和c++的关系,他们有什么区别?
1、都是面向对象的的语言,都支持封装、继承和多态。
2、c++支持指针而java没有指针这个概念;
3、c++支持多继承,而java不支持多继承,但允许一个类实现多个接口
4、java自动进行无用的内存回收操作,不需要程序员手动删除,而c++中必须由程序员释放内存资源。
5、java不支持操作符重载,操作符重载被认为是c++突出的特征;
6、java是完全面向对象的语言,并且取消了c/c++中的结构体和联合体,使编译程序更加简洁;
7、c和c++不支持字符串变量,java中字符串使用类的对象(String和StringBuffer)实现的。
8、goto语句是c/c++的“遗物”,java不提供goto语句,虽然java指定goto语句是关键字,但不支持使用。
- JVM、JRE和JDK的关系是什么?
1、sdk是(Software Development Kit)软件开发工具包
2、JDK是(java development kit)的缩写,它是功能齐全的java SDK。
它拥有JRE所拥有的一切而且还有编译器(javac)和工具(如javadoc和jdb)。
JDK可以创建和编译程序。
3、JRE是(java Runtime Environment)运行时环境,他是运行已编译java程序所需的所有内容的集合,
包括java虚拟机(JVM),java类库,java命令和其他的一些基础构件。
但是他不能用于创建新程序。
4、JVM(java虚拟机)
Java程序的跨平台特性主要是指字节码文件可以在任何具有Java虚拟机的计算机或者电子设备上运行,
Java虚拟机中的Java解释器负责将字节码文件解释成为特定的机器码进行运行。
因此在运行时,Java源程序需要通过编译器编译成为.class文件。众所周知java.exe是java class文件的执行程序,
但实际上java.exe程序只是一个执行的外壳,
它会装载jvm.dll(windows下,下皆以windows平台为例,linux下和solaris下其实类似,为:libjvm.so),
这个动态连接库才是java虚拟机的实际操作处理所在。
5、JDK包含JRE,JER包含JVM。
4.什么是字节码?采用字节码的好处是什么?
1、java之所以可以“一次编译,到处运行”,一、是因为JVM针对各种操作系统、平台都进行了定制
2、是因为无论什么平台,都可以编译生成固定格式的字节码(.class)文件供JVM使用。因此可以看出字节码对于java生态的重要性。
之所以被称为字节码,是因为字节码文件由十六进制值组成,而JVM以两个十六进制值为一组,即以字节为单位进行读取。
java语言通过字节码的方式,在一定程度上解决了传统解释性语言执行效率低的问题,同时又保留了解释性语言可移植的特点,
所以java程序运行时比较高效,而且由于字节码并不针对一种特定的机器,因此,java无需重新编译即可在多种不同的计算机上运行。
java运行过程如下图:
5. Oracle JDK 和 OpenJDK的区别是什么?
1、Oracle JDK版本每三年发布一次,而OpenJDK版本每三个月发布一次;
2、OpenJDK是一个参考模型并且完全开源的,而Oracle JDK是OpenJDK的一个实现并不是完全开源的。
3、OracleJDK比OpenJDK更稳定、性能更好并且有更多的类和一些错误的修复
4、Oracle JDK根据二进制代码许可协议获得许可,而OpenJDK根据GPLv2许可获得许可
- java有哪些数据类型?
1、数据类型有基本数据类型和引用数据类型
2、基本数据类型有:boolean、float、char、byte、short、int、long、double共八种。
3、引用数据类型有:类class,接口interface,数组[]。
4、另外java中不支持c++中的指针类型,结构类型,联合类型和枚举类型。(java5开始就支持枚举类型了历史遗留问题故不作修改)
- switch是否能作用在byte上,是否能作用在long上,是否能作用在String上?
1、java5以前switch表达式只能是byte,short,char,int。
2、从java5开始,java引入枚举类型,expr可以是enum类型。
3、从java7开始,expr可以是字符串(String),但是long在目前所有版本中都是不支持的。
- 访问修饰符public,private,protected,以及不写(默认)时的区别?
1、default(即默认,什么也不写):在同一包内可见,不能使用任何修饰符。使用对象:类、接口、变量、方法。
2、private:在同一类中可以见。使用对象:变量、方法。注意:不能修饰类(外部类)。
3、public:对所有类可见。使用对象:类、接口、变量、方法。
4、protected:对同一包内的类和所有子类可见。使用对象:变量,方法。注意:不能修饰类(外部类)。
- break,continue,return的区别及作用?
1、break跳出循环体,完全结束当前的循环体。
2、continue跳出本次循环,继续执行下一次循环。
3、return程序返回,不再执行下面的代码(结束当前方法直接返回)
- final、finally、finalize的区别?
一、
final用于修饰变量、方法和类。
1、final变量:被修饰的变量不可变、不可变分为:引用不可变和对象不可变,final指的是引用不可变,
final修饰的变量值必须初始化,通常称被修饰的变量为常量。
2、final方法:被修饰的方法不允许任何子类重写,子类可以使用该方法。
3、final类:被修饰的类不能被继承,所有方法不能被重写。
二、
finally作为异常处理的一部分,他只能在try/catch语句中并且附带一个语句块表示这点语句最终一定被执行(无论是否抛出异常),
经常备用在需要是否资源的情况下,System.exit(0)可以阻断finally执行。
三、
finalize是在java.lang.Object里定义的方法,也就是说每一个对象都有这么个方法,这个方法在gc启动,该对象被回收的时候被调用。
一个对象的finalize方法只会被调用一次,finalize被调用不一定会立即回收该对象,
所以有可能finalize后该对象又不需要被回收了,然后到了真正被回收的时候,因为前面以及调用过一次,
所以不会再次调用finalize了,进而产生问题,因此不推荐finalize方法。
- 为什么要用static关键字?
1、方便在没有创建对象时也可以调用变量或方法。
2、而且有时我们需要用静态变量来进行统计,因为静态变量不依赖于对象而是依赖于类而存在。
- static关键字是什么意思?java中是否可以覆盖(override)一个private或者是static的方法?
1、“static”关键字表明一个成员变量或者是成员方法可以在没有所属的类的实例变量的情况下被访问。
Java中static方法不能被覆盖,因为方法覆盖是基于运行时动态绑定的,
而static方法是编译时静态绑定的。static方法跟类的任何实例都不相关,所以概念上不适用。
2、java中也不可以覆盖private的方法,因为private修饰的变量和方法只能在当前类中使用,
如果是其他的类继承当前类是不能访问到private变量或方法的,当然也不能覆盖。
- 是否可以在static环境中访问非static变量?
1、static变量在Java中是属于类的,他在所有实例中的值是一样的。当类被Java虚拟机载入的时候,会对static变量进行初始化。
如果你的代码尝试不用实例来访问非static变量,编译器会报错,因为这些变量还没有被创建出来,还没有跟任何实例关联上。
- static静态方法能不能引用非静态资源?
不能,new的时候才会产生的东西,对于初始化就存在的静态资源来说,根本就不认识它。
- static静态方法里面能不能引用静态资源?
可以,因为都是类初始化的时候加载的,大家相互都认识。
- 非静态方法里面能不能引用静态资源?
可以,非静态方法就是实例方法,那是new之后才产生的,那么属于类的内容它都认识。
- Java静态变量、代码块、和静态方法的执行顺序是什么?
基本上代码块分为三种:Static静态代码块、构造代码块、普通代码块
代码块执行顺序:静态变量or静态代码块->构造代码块->构造方法->普通代码块。
静态代码块:带有Static标识。
构造代码块:类中{}里面的。
构造方法:与类同名的方法。
普通代码块:普通方法中的代码。
继承中代码块的执行顺序:父类静态块->子类静态块->父类代码块->父类构造器->子类代码块->子类构造器。
- 面向对象和面向过程的区别?
1、面向过程:
优点:性能比面向对象高,因为类调用时需要实例化,开销比较大,笔记消耗资源;比如单品机、嵌入式开发、Linux/Unix等一般采用面向过程开发,性能时最重要的因素。
缺点:没有面向对象易维护、易复用、易扩展。
2、面向对象:
优点:易维护、易服用、易扩展,由于面向对象具有封装、继承、多态的特性、可以设计出低耦合的系统,使系统更加灵活,更加易于维护。
缺点:性能比面向过程低。
- 讲讲面向对象的三大特性
1、封装:封装是把客观的事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或对象操作,对不可信的进行信息隐蔽。
2、继承:是指这样一种能力:它可以使用现有的类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩展。
通过继承创建新的类成为‘子类’或‘派生类’,被继承的类称为“基类”、“父类”或“超类”。
3、多态性:父类中的属性和方法被子类继承后可以具有不同的数据类型或表现出不同的行为,这使得同一属性或方法在父类及其各个子类中具有不同的含义。
- Java语言是如何实现多态的?
本质上多态分为两种:
1、编译时的多态(又称为静态多态)
2、运行时的多态(又称为动态多态)
重载就是编译时多态的一个例子,编译时多态在编译时就已经确定,运行的时候调用的是确定的方法。
我们通常所说的多态指的都是运行时的多态,也就是编译时不确定究竟调用哪个方法,一直延迟到运行时才能确定。
这也就是为什么多态方法又被称为延迟方法。
Java实现多态有三个必要条件:继承、重写和向上转型。
只有满足这三个条件,开发人员才能在同一个继承结构中使用统一的逻辑实现代码处理不同的对象,从而执行不同的行为。
继承:在多态中必须存在继承关系的子类和父类
重写:子类对父类中某些方法进行重新定义,在调用这些方法时就会调用子类的方法。
向上转型:在多态中需要将父类的引用指向子类的对象,只有这样该引用才既能可以调用父类的方法,又能调用子类的方法。
- 重载(overload)和重写(override)的区别是什么?
方法的重载和重写都是实现多态的方式,区别在于前者实现的时编译时的多态性,
而后者实现的时运行时的多态性。
1、重写发生在子类与父类之间,重写方法的返回值和形参都不能改变,
2、重载是在一个类里面,方法名字相同,而参数不同。返回类型可以相同也可以不同。
每个重载的方法都必须有一个独一无二的参数类型表。
最常用的地方就是构造器重载。
- 重载的方法能否根据返回值类型进行区分?
不能,因为调用时不能指定类型的信息,编译器不知道你要调用哪个函数。
- 构造器(constructor)是否可被重写(override)?
构造器不能被继承,因此不能被重写,但可以被重载。
每一个类都必须有自己的构造方法,负责构造自己这一部分。
子类不会覆盖父类的构造函数,相反必须一开始调用父类的构造函数。
- 抽象类和接口的区别是什么?
一、语法层面上的区别:
1、抽象类可以提供成员方法的实现细节,而接口中只能存在public abstract 方法;
2、抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是public static final类型的;
3、接口中不能含有静态代码块以及静态方法,而抽象类可以有静态代码块和静态方法;
4、一个类只能继承一个抽象类,而一个类却可以实现多个接口。
二、设计层面上:抽象类是对一种事物的抽象,即对类的抽象,而接口是对行为的抽象。
抽象类是对整个类整体进行抽象,包括属性、行为、但是接口却是对类局部(行为)进行抽象。
举个例子来理解:飞机和鸟是不同类的事物,但是他们都有一个共性,就是都会飞。
那么在设计的时候,可以将飞机设计为一个类Airplane,将鸟设计为一个类Bird,
但是不能将飞行这个特性也设计为类,因为他只是一个行为的特征,并不是对一类事物的抽象描述。
此时可以将 飞行 设计为一个接口Fly,包含方法fly( ),然后Airplane和Bird分别根据自己的需要实现Fly这个接口。
然后至于有不同种类的飞机,比如战斗机、民用飞机等直接继承Airplane即可,
对于鸟也是类似的,不同种类的鸟直接继承Bird类即可。
从这里可以看出,继承是一个 "是不是"的关系,而 接口 实现则是 "有没有"的关系。
如果一个类继承了某个抽象类,则子类必定是抽象类的种类,而接口实现则是有没有、具备不具备的关系,
比如鸟是否能飞(或者是否具备飞行这个特点),能飞行则可以实现这个接口,不能飞行就不实现这个接口。
抽象类作为很多子类的父类,它是一种模板式设计。
而接口是一种行为规范,它是一种辐射式设计。
- 抽象类能使用final修饰吗?
final意味着最终final修饰的类不能被继承。
不能,定义抽象类就是让其它类继承的,如果定义为final该类就不能被继承,
这样彼此就会产生矛盾,所以final泵修饰抽象类
- Java创建对象有哪些方式?
Java提供了五种创建对象的方式:
1、new关键字;People people = new People();
2、采用反射机制:
2.1:class.newInstance
eg:People people = People.class.newInstance();
2.2:Constructor.newInstance
eg:Constructor<People> constructor = People.class.getConstructor();
People people = constructor.newInstance();
3、采用clone机制:
无论何时我们调用一个对象的clone方法,JVM就会创建一个新的对象,将前面对象的内容全部拷贝进去,用clone方法创建对象并不会调用任何构造函数。
要使用clone方法,我们必须先实现Cloneable接口并复写Object的clone方(因为Object的这个方法是protected的,你若不复写,外部也调用不了呀)。
public class People implements Cloneable {
private String name;
public People() {
}
@Override
public People clone() throws CloneNotSupportedException {
return (People) super.clone();
}
public void say() {
System.out.println("I'm wjq!");
}
}
浅拷贝和深拷贝的区别:
如果在拷贝这个对象的时候,只对基本数据类型进行了拷贝,而对引用数据类型只是进行了引用的传递,而没有创建一个新的对象,那就是浅拷贝。
反之,在对引用数据类型进行拷贝的时候,新创建了一个新的对象,并完全复制了其内的成员变量,那么这就是深拷贝。
实际浅拷贝和深拷贝只是相对的,如果一个对象内部只有基本数据类型,那用 clone() 方法获取到的就是这个对象的深拷贝,
而如果其内部还有引用数据类型,那用 clone() 方法就是一次浅拷贝的操作。
People people = new People();
People clonePeople = people.clone();
4、通过序列化机制:
Java序列化是指把Java对象转换为字节序列的过程;
而Java反序列化是指把字节序列恢复为Java对象的过程。
序列化分为两大部分:序列化和反序列化。
序列化是这个过程的第一部分,将数据分解成字节流,以便存储在文件中或在网络上传输。
反序列化就是打开字节流并重构对象。对象序列化不仅要将基本数据类型转换成字节表示,有时还要恢复数据。恢复数据要求有恢复数据的对象实例。
只有实现了Serializable或者Externalizable接口的类的对象才能被序列化为字节序列。(不是则会抛出异常)
- 什么是不可变对象?好处是什么?
不可变对象指对象:对象一旦被创建后,对象所有的状态及属性在其生命周期内不会发生任何变化。任何修改都会创建一个新的对象,如:String、Integer及其它包装类。
不可变对象最大的好处是线程安全。
- 能否创建一个包含可变对象的不可变对象?
当然可以。这就是一个例子:final People[] peoples = new People []{};
peoples是不可变对象的引用,但People的实例确实可变的。
这种情况下需要金属,不要共享可变对象的引用,在这种情况下,如果数据需要变化时,就返回对象的一个拷贝。
- 值传递和引用传递的区别?为什么说Java只有值传递?
1、值传递:指的是在方法调用时,传递的参数是安值的拷贝传递,传递的是值的拷贝,也就是说传递后就互不相关了。
2、引用传递:指的是在方法调用时,传递的参数是按照引用传递,其实传递的是引用的地址,也就是变量所对应的内存空间地址。
传递的是值的引用,也就是说传递前和传递后都是指向同一个引用(同一个内存空间)。
3、基本数据类型是值传递,引用类型作为参数被传递时也是值传递,只不过‘值’为对应的引用。
- ==和equals区别是什么?
1、==常用于相同的基本数据类型直接的比较,也可用于相同类型的对象之间的比较;
如果==比较的是基本数据类型,那么比较的是两个基本数据类型的值是否相等。
如果==比较的是两个对象,那么比较的是两个对象的引用,也就是判断两个对象是否指向了同一块内存区域。
2、equals方法之一用于两个对象之间,检查一个对象是否等于另一个对象
看一看Object类中的equals方法的源码:
public boolean equals(Object obj) {
return (this == obj);
}
它的作用也是判断两个对象是否相等,一般有两种情况:
情况1,类没有覆盖equals()方法,则通过equals()比较该类的两个对象时等价于通过‘==’比较;
情况2,类覆盖了equals()方法,一般,我们都覆盖equals()方法来比较两个对象的内容是否相等;
若他们的内容相等则返回true;
Java语言要求equals方法具有以下特性:
自反性:对于任意不为null的引用值下,x.equals(x)一定时true;
对称性:对于任意不为null的引用值x和y,当且仅当x.equals(y)是true,y.eqals(x)也是true。
传递性:对于任意不为null的引用值x,y,z,如果x.equals(y)==true同时y.equals(z)那么x.equals(z)也一定是true。
一致性:对于任意的不为null的引用值x和y,如果用于equals比较的对象信息没有被修改,那么多次调用equals的值应该是一致的。
对于任意不为null的引用值x,x.equals(null)返回false
- 介绍下hashCode()?
hashCode()的作用是获取哈希码,也称为散列码;它实际上是返回一个int整数。
哈希码的作用是确定该对象在哈希表中索引的位置。hashCode()定义在JDK的Object.Java中,这就意味着Java中的任何类都包含hashCode()函数。
哈希表存储的是(key-value),他的特点是:能根据键快速的索引对应的‘值’。
这其中就用到了哈希码。
- 为什么要有hashCode?
以“HashSet如何检查”为例子来说明为什么要有hashCode:
当你把对象加入HashSet时,HashSet会先计算对象的hashcode值来判断对象加入的位置,同时也会与其他已经加入的对象的hashcode值相比较,如果没有相符合的
hashCode,Hashset就会假设对象没有重复出现。
若发现有相同的Hashcode值的对象,这时就会调用equals()方法,来检查hashcode想的的对象是否真的相等,若相同则Hashset就不会让其加入操作成功。
若不同就会重新散列到其他位置,这样我们就大大减少equals的次数,相应就大大提高了执行的速度。
- hashCode(),equals()两种方法时什么关系?
如果两个对象 equals,Java 运行时环境会认为他们的 hashCode 一定相等。
如果两个对象不 equals,他们的 hashCode 有可能相等。
如果两个对象 hashCode 相等,他们不一定 equals。
如果两个对象 hashCode 不相等,他们一定不 equals
补充:关于 equals() 和 hashCode() 的重要规范
规范1:若重写 equals() 方法,有必要重写 hashcode()方法,确保通过 equals()方法判断
结果为 true 的两个对象具备相等的 hashcode() 方法返回值。说得简单点就是:“如果两
个对象相同,那么他们的 hashCode 应该相等”。不过请注意:这个只是规范,如果非要
写一个类让 equals() 方法返回 true 而 hashCode() 方法返回两个不相等的值,编译和运
行都是不会报错的。不过这样违反了 Java 规范,程序也就埋下了 BUG。
规范2:如果 equals() 方法返回 false,即两个对象“不相同”,并不要求对这两个对象调用
hashCode() 方法得到两个不相同的数。说的简单点就是:“如果两个对象不相同,他们的
hashCode 可能相同”。
- 为什么重写equals方法必须重写hashcode方法?
先根据hashcode进行的判断,相同的情况下再根据equals()方法进行判断。如果只重写了equals方法,而不重写hashcode的方法,会造成hashcode的值不同,
而equals()方法判断出来的结果为true。
在Java中的一些容器中,不允许有两个完全相同的对象,插入的时候,如果判断相同则会进
行覆盖。这时候如果只重写了equals()的方法,而不重写hashcode的方法,Object中
hashcode是根据对象的存储地址转换而形成的一个哈希值。这时候就有可能因为没有重写hashcode方法,
造成相同的对象散列到不同的位置而造成对象的不能覆盖的问题。
Java中set不允许两个完全相同的对象,如果不重写hashcode会导致两个相同的对象存在于set中。
- String,StringBuffer,StringBuilder的区别是什么?
1、可变与不可变。
String类中使用字符数组保存字符串,因为有“final”修饰符,所以string对象是不可变的。
对于已经存在的String对象的修改都是重新创建一个新的对象,然后把新的值保存进去.
private final char value[];
StringBuilder与StringBuffer都继承自AbstractStringBuilder类,在AbstractStringBuilder中也是使用字符数组保存字符串,这两种对象都是可变的。
char[] value;
2、线程安全
String中的对象是不可变的,也就可以理解为常量,显然线程安全。
StringBuilder是非线程安全的。因为count += len不是一个原子操作。
假设这个时候count值为10,len值为1,两个线程同时执行到了第七行,拿到的count值都是10,执行完加法运算后将结果赋值给count,
所以两个线程执行完后count值为11,而不是12。
StringBuffer对方法加了同步锁或者对调用的方法加了同步锁,所以是线程安全的。
3、效率
如果你只是在单线程中使用字符串缓冲区,那么StringBuilder的效率会更高些。值得注意的
是StringBuilder是在JDK1.5版本中增加的。以前版本的JDK不能使用该类。
- String为什么要设计成不可变的?
1、便于实现字符串池(String pool)
字符串池是方法区中的一部分特殊存储。当一个字符串被被创建的时候,首先会去这个字符串池中查找,如果找到,直接返回对该字符串的引用。
2、使线程安全
在并发场景下,多个线程同时读一个资源,是安全的,不会引发竞争,
但对资源进行写操作时是不安全的,不可变对象不能被写,所以保证了多线程的安全。
3、避免安全问题
在网络连接和数据库连接中字符串常常作为参数,例如,网络连接地址URL,文件路径path,反射机制所需要的String参数。其不可变性可以保证连接的安全性。
如果字符串是可变的,黑客就有可能改变字符串指向对象的值,那么会引起很严重的安全问题。
4、加快字符串处理速度
由于String是不可变的,保证了hashcode的唯一性,于是在创建对象时其hashcode就可以放心的缓存了,不需要重新计算。
这也就是Map喜欢将String作为Key的原因,处理速度要快过其它的键对象。所以HashMap中的键往往都使用String。
总体来说,String不可变的原因要包括 设计考虑,效率优化,以及安全性这三大方面。
- 字符型常量和字符串常量的区别?
1、形式上:字符常量是单引号引起的一个字符,字符串常量是双引号引起的若干个字符;
2、含义上:: 字符常量相当于一个整型值( ASCII 值),可以参加表达式运算;字符串常量代表一个地址值(该字符串在内存中存放位置,相当于对象;)
3、占内存大小:字符常量只占2个字节;字符串常量占若干个字节(至少一个字符结束标志)(注意: char 在Java中占两个字节)。
- 什么是字符串常量池
Java为了提升性能和减少内存开销,会避免字符串重复创建,其维护了一块特殊的内存空间,即字符串池。
当需要使用字符串时,先去字符串池中查看是否字符串已经存在,如果存在,则可以直接使用;
若不存在则初始化,并将字符串加入字符串池中。
- String str="aaa"与String str=newString("aaa")一样吗? new String(“aaa”);创建了几个字符串对象?
使用String a = "aaa";程序运行会在常量池中查找“aaa”字符串,若没有,会将“aaa”字符串放进常量池,再将其地址赋给a;
若有,将找到“aaa”字符串的地址赋给a。
使用string b = new String(“aaa”);程序会开辟一个新的空间存放新的对象,同时将“aaa”字符串放进常量池中,相当于创建了两个对象;
1、这里的aa在之后类加载的时候,会在字符串常量池里创建一个 "aa"对象,这是第一个对象
2、类加载完成了之后,那就要开始正式执行代码了,执行该行代码时new一个"aa"的String对象存放在Java堆中,这是第二个对象
3、创建完第二个对象后,虚拟机栈上的str1将会指向第二个对象,也就是堆上的对象
- String是最基本的数据类型吗?
- String有哪些特性?
- 在使用HashMap的时候,用String做key有什么好处?
- 包装类型是什么?基本数据类型和包装类型有什么区别?
- 解释一下自动装箱和自动拆箱?
- int和Integer有什么区别?
Java类加载机制?
向上委托:查找缓存是否加载该类,有则返回,无则继续向上
向下查找:查找加载路径,有则返回,无则向下继续查找
Mysql基础
- 数据库的三范式是什么?
1、第一范式:强调的是列的原子性,即数据库表的每一列都是不可分割的原子数据项。
2、第二范式:要求实体的属性完全依赖于主关键字。
3、第三范式:任何非主属性不依赖于其它非主属性。
- MySQL支持哪些存储引擎?
Mysq支持多种存储引擎,比如InnoDB,MyISAM,Memory,Archive等等。
在大多数情况下直接使用InnoDB引擎都是最合适的,InnoDB也是MySQL的默认存储引擎。
InnoDB和MyISAM的区别?
InnoDB支持事务,MyISAM不支持;
InnoDB支持外键,而MyISAM不支持;
InnoDB是聚集索引,数据文件是和索引绑在一起的,必须要有主键,通过主键索引效率哼;
MyISAM是非聚集索引,数据文件是分离的,索引保存的是数据文件的指针,主键索引和辅助索引是独立的;
InnoDB不支持全文索引,而MyISAM支持全文索引,查询效率上MyISAM要高;
InnoDB不保存表的具体行数,MyISAM用一个变量保存了整个表的行数。
MyISAM采用表级锁,InnoDB支持行级锁和表级锁,默认为行级锁;
- 超键、候选键、主键、外键区别是什么?
超键:在关系中能为一标识元组的属性集称为关系模式的超键。
一个属性可以做运维超键,多个属性组合在一起也可以作为一个超键。超键包含候选键和主键。
候选键:最小的超键,即没有冗余元素的超键。
主键:数据库表中对储存数据对象予以唯一和完整表示的数据列和属性的组合。
一个数据列只能有一个主键,且主键的取值不能缺失(NULL);
外键:在一个表中存在的另一个表的主键称此表的外键。
学生信息(学号 身份证号 性别 年龄 身高 体重 宿舍号)和 宿舍信息(宿舍号 楼号)
超键:只要含有“学号”或者“身份证号”两个属性的集合就叫超键,例如R1(学号 性别)、R2(身份证号 身高)、R3(学号 身份证号)等等都可以称为超键!
候选键:不含有多余的属性的超键,比如(学号)、(身份证号)都是候选键,又比如R1中学号这一个属性就可以唯一标识元组了,而有没有性别这一属性对是否唯一标识元组没有任何的影响!
主键:就是用户从很多候选键选出来的一个键就是主键,比如你要求学号是主键,那么身份证号就不可以是主键了!
外键:宿舍号就是学生信息表的外键
- SQL约束有哪几种?
NOT NULL:用于控制字段的内容一定不能为空(NULL);
UNIQUE:控件字段内容不能重复,一个表允许有多个Unique约束。
PRIMARY KEY:用于控件字段内容不能重复,但它在一个表只允许出现一个。
FOREIGN KEY:用于预防破坏表之间连接的动作,也能防止非法数据插入外键列,因为他必须是它指向的那个表中的值之一。
CHECK:用于控制字段的值范围。
- MySQL中的varchar和char有什么区别?
char是一个定长字段,假如申请了char(10)空间,那么无论实际存储多少内容,该字段都占有10个字符;
而varchar是变成的,也就是说申请的只是最大长度,占用的空间为世界字符长度+1,最后一个字符存储使用了多长的空间。
在检索效率上来讲,char > varchar,因此在使用中如果确实某个字段的值的长度,可以使用char,否则应该尽量使用varchar。
例如存储用户MD5加密后的密码,则应该使用char。
- MysQL中in和exists区别?
MySQL中的in语句是把外部和内表做hash连接,
分库分表的之后的问题:
1、联合查询困难
联合查询不仅困难,而且可以说是不可能,因为两个相关联的表可能会分布在不同的数据库,不同的服务器中。
2、需要支持事务
分库分表后,就需要支持分布式事务了。数据库本身为我们提供了事务管理功能,但是分库分表之后就不适用了。
如果我们自己编程协调事务,代码方面就又开始了麻烦。
3、跨库join困难
分库分表后表之间的关联操作将受到限制,我们无法join位于不同分库的表,也无法join分表粒度不同的表,
结果原本一次查询能够完成的业务,可能需要多次查询才能完成。 我们可以使用全局表,所有库都拷贝一份。
4、结果合并麻烦
比如我们购买了商品,订单表可能进行了拆分等等,此时结果合并就比较困难。