java基础随笔
⚫ java面向对象:
1)继承:继承是从已有类得到继承信息创建新类的过程。提供继承信息的类被称为父类(超类、基类);得到继承信息的类被称为子类(派生类)。继承让变化中的软件系统有了一定的延续性,同时继承也是封装程序中可变因素的重要手段。
2) 封装:通常认为封装是把数据和操作数据的方法绑定起来,对数据的访问只能通过已定义的接口。面向对象的本质就是将现实世界描绘成一系列完全自治、封闭的对象。我们在类中编写的方法就是对实现细节的一种封装;我们编写一个类就是对数据和数据操作的封装。可以说,封装就是隐藏一切可隐藏的东西,只向外界提供最简单的编程接口。
3) 多态性:多态性是指允许不同子类型的对象对同一消息作出不同的响应。简单的说就是用同样的对象引用调用同样的方法但是做了不同的事情。多态性分为编译时的多态性和运行时的多态性。如果将对象的方法视为对象向外界提供的服务,那么运行时的多态性可以解释为:当A系统访问B系统提供的服务时,B系统有多种提供服务的方式,
但一切对 A 系统来说都是透明的。方法重载(overload)实现的是编译时的多态性(也称为前绑定),而方法重写(override)实现的是运行时的多态性(也称为后绑定)。运行时的多态是面向对象最精髓的东西,要实现多态需要做两件事:1. 方法重写(子类继承父类并重写父类中已有的或抽象的方法);2. 对象造型(用父类型引用引用子类型对象,这样同样的引用调用同样的方法就会根据子类对象的不同而表现出不同的行为)。
⚫ & 和 && 的区别:
1、&和&&都可以用作逻辑与的运算符,表示逻辑,当运算符两边的表达式的结果都为true时,整个运算结果才为true,否则,只要有一方为false,则结果为false。
2、&&还具有短路的功能,即如果第一个表达式为false,则不再计算第二个表达式。
例如,对于if(str != null && !str.equals(“”))表达式,当str为null时,后面的表达式不会执行,所以不会出现NullPointerException,如果将&&改为&,则会抛出NullPointerException异常。
3、&还可以用作位运算符,当&操作符两边的表达式不是boolean类型时,&表示按位与操作,我们通常使用0x0f来与一个整数进行&运算,来获取该整数的最低4个bit位,例如,0×31 & 0x0f的结果为0×01。
⚫ 解释内存中的栈(stack)、堆(heap)和方法区(method area)的用法。
1、栈的使用:通常我们定义一个基本数据类型的变量,一个对象的引用,还有就是函数调用的现场保存都使用JVM中的栈空间。
2、堆的使用:通过new关键字和构造器创建的对象则放在堆空间,堆是垃圾收集器管理的主要区域。
3、方法区的使用:方法区和堆都是各个线程共享的内存区域,用于存储已经被JVM加载的类信息、常量、静态变量、JIT编译器编译后的代码等数据;程序中的字面量(literal)如直接书写的100、"hello"和常量都是放在常量池中,常量池是方法区的一部分。
栈空间操作起来最快但是栈很小,通常大量的对象都是放在堆空间,栈和堆的大小都可以通过JVM的启动参数来进行调整,栈空间用光了会引发StackOverflowError,而堆和常量池空间不足则会引发OutOfMemoryError。
⚫ 在 Java 中,如何跳出当前的多重嵌套循环?
在Java中,要想跳出多重循环,可以在外面的循环语句前定义一个标号,然后在里层循环体的代码中使用带有标号的break 语句,即可跳出外层循环
⚫ 构造器(constructor)是否可被重写(override)?
构造器不能被继承,因此不能被重写,但可以被重载。
⚫ String 是最基本的数据类型吗?
不是。Java 中的基本数据类型只有 8 个:byte、short、int、long、float、double、 char、boolean;除了基本类型(primitive type),剩下的都是引用类型(reference type),Java 5 以后引入的枚举类型也算是一种比较特殊的引用类型。
⚫ 内部类与静态内部类的区别?
静态内部类相对与外部类是独立存在的,在静态内部类中无法直接访问外部类中变量、方法。如果要访问的话,必须要new一个外部类的对象,使用new出来的对象来访问。但是可以直接访问静态的变量、调用静态的方法;
普通内部类作为外部类一个成员而存在,在普通内部类中可以直接访问外部类属性,调用外部类的方法。
如果外部类要访问内部类的属性或者调用内部类的方法,必须要创建一个内部类的对象,使用该对象访问属性或者调用方法。
如果其他的类要访问普通内部类的属性或者调用普通内部类的方法,必须要在外部类中创建一个普通内部类的对象作为一个属性,外同类可以通过该属性调用普通内部类的方法或者访问普通内部类的属性
如果其他的类要访问静态内部类的属性或者调用静态内部类的方法,直接创建一个静态内部类对象即可。
⚫ Char类型能不能转成int类型?能不能转化成string类型,能不能转成double类型
Char在java中也是比较特殊的类型,它的int值从1开始,一共有2的16次方个数据;
Char<int<long<float<double;Char类型可以隐式转成int,double类型,但是不能隐式转换成string;如果char类型转成byte,short类型的时候,需要强转。
⚫ 两个对象值相同(x.equals(y) == true),但却可有不同的hash code,这句话对不对?
不对,如果两个对象 x 和 y 满足 x.equals(y) == true,它们的哈希码(hash code)应当相同。
Java 对于 eqauls 方法和 hashCode 方法是这样规定的:
(1)如果两个对象相同(equals 方法返回 true),那么它们的 hashCode 值一定要相同;
(2)如果两个对象的 hashCode 相同,它们并不一定相同。
当然,你未必要按照要求去做,但是如果你违背了上述原则就会发现在使用容器时,相同的对象可以出现在 Set 集合中,同时增加新元素的效率会大大下降(对于使用哈希存储的系统,如果哈希码频繁的冲突将会造成存取性能急剧下降)。
⚫ 当一个对象被当作参数传递到一个方法后,此方法可改变这个对象的属性,并可返回变化后的结果,那么这里到底是值传递还是引用传递?
是值传递。Java 语言的方法调用只支持参数的值传递。当一个对象实例作为一个参数被传递到方法中时,参数的值就是对该对象的引用。对象的属性可以在被调用过程中被改变,但对对象引用的改变是不会影响到调用者的。C++和 C#中可以通过传引用或传输出参数来改变传入的参数的值。在 C#中可以编写如下所示的代码,但是在 Java 中却做不到。
⚫ a.hashCode() 有什么用?与 a.equals(b) 有什么关系?
hashCode() 方法是相应对象整型的 hash 值。它常用于基于 hash 的集合类, 如 Hashtable、HashMap、LinkedHashMap 等等。它与 equals() 方法关系特别紧密。根据 Java 规范,两个使用equal() 方法来判断相等的对象,必须具有相同的 hash code。
⚫ 阐述静态变量和实例变量的区别。
在语法定义上的区别:静态变量前要加static关键字,而实例变量前则不加。
在程序运行时的区别:实例变量属于某个对象的属性,必须创建了实例对象,其中的实例变量才会被分配空间,才能使用这个实例变量。静态变量不属于某个实例对象,而是属于类,所以也称为类变量,只要程序加载了类的字节码,不用创建任何实例对象,静态变量就会被分配空间,静态变量就可以被使用了。总之,实例变量必须创建对象后才可以通过这个对象来使用,静态变量则可以直接使用类名来引用。
⚫ 类加载过程
1、Jvm先去方法区下找类是否存在,如果不存在,则把类加载到方法区下
2、先加载非静态内容到方法区下的非静态区域内
3、再加载静态内容到方法区下的静态区域内,并对所有的静态成员变量进行默认初始化,再对所有的静态成员变量显式初始化
4、JVM自动执行静态代码块(静态代码块在栈中执行)[如果有多个静态代码,执行的顺序是按照代码书写的先后顺序执行]
5、所有的静态代码块执行完成之后,此时类的加载完成
⚫ 对象创建过程
1、JVM会先去方法区下找有没有所创建对象的类存在,有就可以创建对象了,没有则把该类加载到方法区
2、在创建类的对象时,首先会先去堆内存中分配空间
3、当空间分配完后,加载对象中所有的非静态成员变量到该空间下
4、所有的非静态成员变量加载完成之后,对所有的非静态成员进行默认初始化
5、所有的非静态成员默认初始化完成之后,调用相应的构造方法到栈中
6、在栈中执行构造函数时,先执行隐式,再执行构造方法中书写的代码
7、执行顺序:静态代码库,构造代码块,构造方法
8、当整个构造方法全部执行完,此对象创建完成,并把堆内存中分配的空间地址赋给对象名(此时对象名就指向了该空间)
⚫ Integer与int的区别
int是java提供的8种原始数据类型之一。Java为每个原始类型提供了封装类,Integer是java为int提供的封装类。int的默认值为0,而Integer的默认值为null,即Integer可以区分出未赋值和值为0的区别,int则无法表达出未赋值的情况,例如,要想表达出没有参加考试和考试成绩为0的区别,则只能使用Integer。
⚫ 为什么在重写了equals()方法之后也必须重写hashCode()方法?
在创建的类不重写hashCode()和equals() 方法时,默认使用 java 提供的 java.lang.Object 下的 hashCode()和equals() 方法。
注意:Object 的public boolean equals(Object obj)方法主要是对非空对象的引用地址的判断相同才返回true,而非对象本身的字符串内容或数值是否相同。
简而言之,当且仅当 值A 和 值B 都是引用自同一个对象时,此方法才会返回true;
所以,当我们重写一个对象,重写了equals()方法后,通常必须重写 hashCode()方法,以维护 hashCode 方法的常规协定,该协定声明了相等对象必须具有相等的哈希码。
说白了,就是equals 返回true的两个值,在hashCode() 中结果也必然是true。
例子:
(1)当obj1.equals(obj2)为true时,obj1.hashCode() == obj2.hashCode()必须为true
(2)当obj1.hashCode() == obj2.hashCode()为false时,obj1.equals(obj2)必须为false
这里引出一个问题,为什么要重写equals()方法呢?难道原生的不能用吗?
答案是必须重写,从前面的注意事项中可以知道,如果不重写equals 方法,那么比较的将是对象的引用是否指向同一块内存地址,而我们重写的目的是为了能够比较两个对象的value值是否相等。
在高级类的八个包装类与引用类型的String类型(该类对euqals和hashcode方法进行了重写)中都 是使用重写后的 equals 方法来比较对象的,默认比较的是值,在比较其它自定义对象时都是比较的引用地址。
后面会对equals 和 hashcode 的关系进行关联解释。
hashcode是用于散列数据的快速存取,如利用HashSet/HashMap/Hashtable类来存储数据时,都是根据存储对象的hashcode值来进行判断是否相同的。
那么,如果我们值重写equals ,而不重写 hashcode 会怎么样?
如果我们对一个对象重写了equals 方法,意味着只要对象的成员变量值都相等那么equals 就返回true ,但在不重写 hashcode 方法的情况下,当我们重新 new 了一个新对象。
此时,当原对象.equals(新对象)等于true时,两者的 hashcode 却是不一样的,由此会产生了理解的不一致,也违反了equals 与 hashcode的约定规则。
不重写导致的结果案例:
在不重写hashcode的情况下,如果 hashset存储两个引用不同但值相同的对象,此时hashcode返回false,认为后者与前者不重复,则会重新 newNode() 创建一个新节点将重复的值添加到集合中,意味着不可重复的单列集合中出现了两个值一样的对象,导致混淆。(假设没有重写)
所以,需要重写 hashcode()方法。
重写equals方法时需要重写hashCode方法,主要是针对Map、Set等集合类型的使用;
a: Map、Set等集合类型存放的对象必须是唯一的;
b: 集合类判断两个对象是否相等,是先判断equals是否相等,如果equals返回TRUE,还要再判断HashCode返回值是否ture,只有两者都返回ture,才认为该两个对象是相等的。
2、由于Object的hashCode返回的是对象的hash值,所以即使equals返回TRUE,集合也可能判定两个对象不等,所以必须重写hashCode方法,以保证当equals返回TRUE时,hashCode也返回Ture,这样才能使得集合中存放的对象唯一。
⚫ 是否可以从一个静态(static)方法内部发出对非静态(non-static)方法的调用?
不可以,静态方法只能访问静态成员,因为非静态方法的调用要先创建对象,在调用静态方法时可能对象并没有被初始化。
⚫ String s = new String(“xyz”);创建了几个字符串对象?
两个对象,一个是静态区的”xyz”,一个是用 new 创建在堆上的对象。
⚫ 接口有什么特点?
接口中声明全是public static final修饰的常量
接口中所有方法都是抽象方法
接口是没有构造方法的
接口也不能直接实例化
接口可以多继承
⚫ Hashcode的作用
java的集合有两类,一类是List,还有一类是Set。前者有序可重复,后者无序不重复。当我们在set中插入的时候怎么判断是否已经存在该元素呢,可以通过equals方法。但是如果元素太多,用这样的方法就会比较满。
于是有人发明了哈希算法来提高集合中查找元素的效率。 这种方式将集合分成若干个存储区域,每个对象可以计算出一个哈希码,可以将哈希码分组,每组分别对应某个存储区域,根据一个对象的哈希码就可以确定该对象应该存储的那个区域。
hashCode方法可以这样理解:它返回的就是根据对象的内存地址换算出的一个值。这样一来,当集合要添加新的元素时,先调用这个元素的hashCode方法,就一下子能定位到它应该放置的物理位置上。如果这个位置上没有元素,它就可以直接存储在这个位置上,不用再进行任何比较了;如果这个位置上已经有元素了,就调用它的equals方法与新元素进行比较,相同的话就不存了,不相同就散列其它的地址。这样一来实际调用equals方法的次数就大大降低了,几乎只需要一两次。
⚫ 抽象的(abstract)方法是否可同时是静态的(static),是否可同时是本地方法(native),是否可同时被 synchronized修饰?
都不能。
抽象方法需要子类重写,而静态的方法是无法被重写的,因此二者是矛盾的。
本地方法是由本地代码(如C代码)实现的方法,而抽象方法是没有实现的,也是矛盾的。
synchronized和方法的实现细节有关,抽象方法不涉及实现细节,因此也是相互矛盾的。
⚫ float f=3.4;是否正确?
不正确。3.4 是双精度数,将双精度型(double)赋值给浮点型(float)属于下转型(down-casting,也称为窄化)会造成精度损失,
因此需要强制类型转换float f =(float)3.4; 或者写成 float f =3.4F;。
⚫ short s1 = 1; s1 = s1 + 1;有错吗?short s1 = 1; s1 += 1;有错吗?
对于 short s1 = 1; s1 = s1 + 1;由于 1 是 int 类型,因此 s1+1 运算结果也是 int型,需要强制转换类型才能赋值给 short 型。而 short s1 = 1; s1 += 1;可以正确编译,
因为 s1+= 1;相当于 s1 = (short)(s1 + 1);其中有隐含的强制类型转换。
⚫ 两个对象值相同 (x.equals(y) == true) ,但却可有不同的hashCode,这句话对不对?
不对,如果两个对象 x 和 y 满足 x.equals(y) == true,它们的哈希码(hashCode)应当相同。 Java 对于eqauls 方法和 hashCode 方法是这样规定的:(1)如果两个对象相同(equals 方法返回 true),那么它们的hashCode 值一定要相同;(2)如果两个对象的 hashCode 相同,它们并不一定相同
⚫ break和continue的区别?
break和continue都是用来控制循环的语句。
break用于完全结束一个循环,跳出循环体执行循环后面的语句。
continue用于跳过本次循环,执行下次循环。
⚫ Java中有几种数据类型?
整形:byte,short,int,long
浮点型:float,double
字符型:char
布尔型:boolean
⚫ ++i与i++的区别
i++:先赋值,后计算
++i:先计算,后赋值
⚫ Java中各种数据默认值
Byte,short,int,long默认是都是0
Boolean默认值是false
Char类型的默认值是’’
Float与double类型的默认是0.0
对象类型的默认值是null
⚫ java中是值传递引用传递?
理论上说,java都是引用传递,对于基本数据类型,传递是值的副本,而不是值本身。对于对象类型,传递是对象的引用,当在一个方法操作操作参数的时候,其实操作的是引用所指向的对象。
⚫ final、finally、finalize的区别
1)final:用于声明属性,方法和类,分别表示属性不可变,方法不可覆盖,被其修饰的类不可继承。
2)finally:异常处理语句结构的一部分,表示总是执行。
3)finalize:Object类的一个方法,在垃圾回收器执行的时候会调用被回收对象的此方法,可以覆盖此方法
提供垃圾收集时的其他资源回收,例如关闭文件等。该方法更像是一个对象生命周期的临终方法,当该方法
被系统调用则代表该对象即将“死亡”,但是需要注意的是,我们主动行为上去调用该方法并不会导致该对
象“死亡”,这是一个被动的方法(其实就是回调方法),不需要我们调用。
⚫ String 、StringBuilder 、StringBuffer的区别?
String和StringBuffer/StringBuilder,它们都可以储存和操作字符串,区别如下。
(1)、可变性
String:字符串常量,是使用数组保存字符串,provate final char value[],在修改时不会改变自身;若修改,等于重新生成新的字符串对象。 底层被final修饰,在修改时会改变对象自身,每次操作都是对StringBuffer对象本身进行修改,不是生成新的对
象;使用场景:对字符串经常改变情况下,主要方法:append(),insert()等。
(2)、线程是否安全
String:对象定义后不可变,线程安全。
StringBuffer:是线程安全的(对调用方法加入同步锁),执行效率较慢,适用于多线程下操作字符串缓冲区大量数据。
StringBuilder:是线程不安全的,适用于单线程下操作字符串缓冲区大量数据。
性能:
相同情况下使用StringBuilder相比使用StringBuffer仅能获得10%-15%左右的性能提升,但是却冒着多线程不安全的风险。
(3)、共同点
StringBuilder与StringBuffer有公共父类AbstractStringBuilder(抽象类)。
StringBuilder、StringBuffer的方法都会调用AbstractStringBuilder中的公共方法,如super.append(...)。
只是 StringBuffer 会在方法上加 synchronized 关键字,进行同步。最后,如果程序不是多线程的,那么使用
StringBuilder效率高于StringBuffer。
⚫ 数据类型之间的转换
(1)、字符串如何转基本数据类型?
调用基本数据类型对应的包装类中的方法parseXXX(String)或valueOf(String)即可返回相应基本类型。
(2)、基本数据类型如何转字符串?
一种方法是将基本数据类型与空字符串(“”)连接(+)即可获得其所对应的字符串;另一种方法是调用String
类中的valueOf()方法返回相应字符串。
⚫ 重载(overload)和重写(override)的区别?重载的方法能否根据返回类型进行区分?
方法重载的规则:
1.方法名一致,参数列表中参数的顺序,类型,个数不同。
2.重载与方法的返回值无关,存在于父类和子类,同类中。
3.可以抛出不同的异常,可以有不同修饰符。
方法重写的规则:
1.参数列表必须完全与被重写方法的一致,返回类型必须完全与被重写方法的返回类型一致。
2.构造方法不能被重写,声明为final的方法不能被重写,声明为static的方法不能被重写,但是能够被再次
声明。
3.访问权限不能比父类中被重写的方法的访问权限更低。
4.重写的方法能够抛出任何非强制异常(UncheckedException,也叫非运行时异常),无论被重写的方法是
否抛出异常。但是,重写的方法不能抛出新的强制性异常,或者比被重写方法声明的更广泛的强制性异常,反之则可以
⚫ 抽象类(abstract class)和接口(interface)有什么异同?
不同:
含有abstract修饰符的class即为抽象类,abstract 类不能创建的实例对象。含有abstract方法的类必须定义为abstract class,abstract class类中的方法不必是抽象的。abstract class类中定义抽象方法必须在具体(Concrete)子类中实现,所以,不能有抽象构造方法或抽象静态方法。如果的子类没有实现抽象父类中的所有抽象方法,那么子类也必须定义为abstract类型。
接口(interface)可以说成是抽象类的一种特例,接口中的所有方法都必须是抽象的。接口中的方法定义默认为public abstract类型,接口中的成员变量类型默认为public static final。
下面比较一下两者的语法区别:
1.抽象类可以有构造方法,接口中不能有构造方法。
2.抽象类中可以有普通成员变量,接口中没有普通成员变量
3.抽象类中可以包含非抽象的普通方法,接口中的所有方法必须都是抽象的,不能有非抽象的普通方法。
4. 抽象类中的抽象方法的访问类型可以是public,protected和(默认类型,虽然
eclipse下不报错,但应该也不行),但接口中的抽象方法只能是public类型的,并且默认即为public abstract类型。
5. 抽象类中可以包含静态方法,接口中不能包含静态方法
6. 抽象类和接口中都可以包含静态成员变量,抽象类中的静态成员变量的访问类型可以任意,但接口中定义的变量只能是public static final类型,并且默认即为public static final类型。
7. 一个类可以实现多个接口,但只能继承一个抽象类。
⚫ Java创建对象有几种方式?
java中提供了以下四种创建对象的方式: 1. new创建新对象
2. 通过反射机制
3. 采用clone机制
4. 通过序列化机制
⚫ JDBC操作的步骤
加载数据库驱动类
打开数据库连接
执行sql语句
处理返回结果
关闭资源
⚫ 接口是否可继承(extends)接口?抽象类是否可实现(implements)接口?抽象类是否可继承具体类(concreteclass)?抽象类中是否可以有静态的main方法?
接 口 可 以 继 承 接 口 , 而 且 支 持 多 重 继 承 。 抽 象 类 可 以 实 现 (implements)接 口 , 抽 象 类 可 继 承 具 体 类 也 可 以 继 承 抽 象 类 ,抽象类中可以有静态的main方法
⚫ 如何实现字符串的反转及替换?
方法很多,可以自己写实现也可以使用 String 或 StringBuffer/StringBuilder 中
的方法。有一道很常见的面试题是用递归实现字符串反转,代码如下所示:
public static String reverse(String originStr) {
if(originStr == null || originStr.length() <= 1)
return originStr;
return reverse(originStr.substring(1)) + originStr.charAt(0);
}
⚫ 内部类可以引用它的包含类(外部类)的成员吗?有没有什么限制?
一个内部类对象可以访问创建它的外部类对象的成员,包括私有成员。
⚫ 有没有可能两个不相等的对象有相同的hashcode
有可能.在产生hash冲突时,两个不相等的对象就会有相同的 hashcode 值.当hash冲突产生时,一般有以下几种方式来处理: 1. 拉链法:每个哈希表节点都有一个next指针,多个哈希表节点可以用next指针构成一个单向链表,被分配到同一个索引上的多个节点可以用这个单向链表进行存储. 2. 开放定址法:一旦发生了冲突,就去寻找下一个空的散列地址,只要散列表足够大,空的散列地址总能找到,并将记录存入
3. 再哈希:又叫双哈希法,有多个不同的Hash函数.当发生冲突时,使用第二个,第三个….等哈希函数计算地址,直到无冲突.
**⚫ JRE 和 JDK **
JRE (Java Runtime Environment) :是Java程序的运行时环境,包含 JVM 和运行时所需要的 核心类库 。 JDK (Java Development Kit):是Java程序开发工具包,包含 JRE 和开发人员使用的工具。 我们想要运行一个已有的Java程序,那么只需安装 JRE 即可。 我们想要开发一个全新的Java程序,那么必须安装 JDK ,其内部包含 JRE 。
⚫ 基本数据类型:
四类八种
⚫ 数据类型转换规则
范围小的类型向范围大的类型提升, byte、short、char 运算时直接提升为 int 。
byte、short、char‐‐>int‐‐>long‐‐>float‐‐>double
⚫ switch语句
表达式的数据类型,可以是byte,short,int,char,enum(枚举),JDK7后可以接收字符串。
⚫ 方法重载:
指在同一个类中,允许存在一个以上的同名方法,只要它们的参数列表不同即可,与修饰符和返 回值类型无关。 参数列表:个数不同,数据类型不同,顺序不同。
⚫ 成员变量和局部变量的区别:
在类中的位置不同 重点 成员变量:类中,方法外 局部变量:方法中或者方法声明上(形式参数)
作用范围不一样 重点 成员变量:类中 局部变量:方法中 初始化值的不同 重点 成员变量:有默认值 局部变量:没有默认值。必须先定义,赋值,最后使用
在内存中的位置不同 了解 成员变量:堆内存 局部变量:栈内存
生命周期不同 了解 成员变量:随着对象的创建而存在,随着对象的消失而消失 局部变量:随着方法的调用而存在,随着方法的调用完毕而消失
**⚫ 和equals的区别? **
equals和 最大的区别是一个是方法一个是运算符。
==:如果比较的对象是基本数据类型,则比较的是数值是否相等;如果比较的是引用数据类型,则比较的是对象
的地址值是否相等。
equals():用来比较方法两个对象的内容是否相等。
注意:equals 方法不能用于基本数据类型的变量,如果没有对 equals 方法进行重写,则比较的是引用类型的变
量所指向的对象的地址
⚫ String常用方法:
public boolean equals (Object anObject) :将此字符串与指定对象进行比较。
public boolean equalsIgnoreCase (String anotherString) :将此字符串与指定对象进行比较,忽略大小 写。
public int length () :返回此字符串的长度。
public String concat (String str) :将指定的字符串连接到该字符串的末尾。
public char charAt (int index) :返回指定索引处的 char值。
public int indexOf (String str) :返回指定子字符串第一次出现在该字符串内的索引。
public String substring (int beginIndex) :返回一个子字符串,从beginIndex开始截取字符串到字符 串结尾。
public String substring (int beginIndex, int endIndex) :返回一个子字符串,从beginIndex到 endIndex截取字符串。含beginIndex,不含endIndex。
public char[] toCharArray () :将此字符串转换为新的字符数组。
public byte[] getBytes () :使用平台的默认字符集将该 String编码转换为新的字节数组。
public String replace (CharSequence target, CharSequence replacement) :将与target匹配的字符串使 用replacement字符串替换。
public String[] split(String regex) :将此字符串按照给定的regex(规则)拆分为字符串数组。
public String toLowerCase() :将字符串转换为小写。
public String toUpperCase() :将字符串转换为大写。
⚫ 操作数组的方法
public static String toString(int[] a) :返回指定数组内容的字符串表示形式。
public static void sort(int[] a) :对指定的 int 型数组按数字升序进行排序。
⚫ Math类
public static double abs(double a) :返回 double 值的绝对值。
public static double ceil(double a) :返回大于等于参数的最小的整数。
public static double floor(double a) :返回小于等于参数最大的整数。
public static long round(double a) :返回最接近参数的 long。(相当于四舍五入方法)
⚫ final关键字
final: 不可改变。可以用于修饰类、方法和变量。 类:被修饰的类,不能被继承。 方法:被修饰的方法,不能被重写。 变量:被修饰的变量,不能被重新赋值。
⚫ 不同权限的访问能力
⚫ 什么是单例模式?有几种?
单例模式:某个类的实例在 多线程环境下只会被创建一次出来。 单例模式有饿汉式单例模式、懒汉式单例模式和双检锁单例模式三种。
双检锁:线程安全,延迟初始化。
⚫ 手写冒泡排序?
⚫ 常见的数据结构有哪些?
数组: 数组是最常用的数据结构,数组的特点是长度固定,可以用下标索引,并且 所有的元素的类型都是一致的。数组常用的场景有:从数据库里读取雇员的信息 存储为 EmployeeDetail[ ];把一个字符串转换并存储到一个字节数组中便于操 作和处理等等。尽量把数组封装在一个类里,防止数据被错误的操作弄乱。另外, 这一点也适合其他的数据结构。 列表: 列表和数组很相似,只不过它的大小可以改变。列表一般都是通过一个固定 大小的数组来实现的,并且会在需要的时候自动调整大小。列表里可以包含重复 的元素。常用的场景有,添加一行新的项到订单列表里,把所有过期的商品移出 商品列表等等。一般会把列表初始化成一个合适的大小,以减少调整大小的次数。 集合: 集合和列表很相似,不过它不能放重复的元素。 堆栈: 堆栈只允许对最后插入的元素进行操作(也就是后进先出,Last In First Out – LIFO)。如果你移除了栈顶的元素,那么你可以操作倒数第二个元素,依次 类推。这种后进先出的方式是通过仅有的 peek(),push()和 pop()这几个方法的 强制性限制达到的。 队列: 队列和堆栈有些相似,不同之处在于在队列里第一个插入的元素也是第一个 被删除的元素(即是先进先出)。这种先进先出的结构是通过只提供 peek(), offer()和 poll()这几个方法来访问数据进行限制来达到的。例如,排队等待公交 车,银行或者超市里的等待列队等等,都是可以用队列来表示。 链表:
链表是一种由多个节点组成的数据结构,并且每个节点包含有数据以及指向 下一个节点的引用,在双向链表里,还会有一个指向前一个节点的引用。例如, 可以用单向链表和双向链表来实现堆栈和队列,因为链表的两端都是可以进行插 入和删除的动作的。当然,也会有在链表的中间频繁插入和删除节点的场景。 Apache 的类库里提供了一个 TreeList 的实现,它是链表的一个很好的替代, 因为它只多占用了一点内存,但是性能比链表好很多。也就是说,从这点来看链 表其实不是一个很好的选择。
⚫ HTTP请求的GET与POST方式的区别
⚫ 重定向和请求转发的区别?
答:1、重定向是服务端产⽣的请求,请求转发是客户端发送的请求
2、重定向只请求⼀次,请求转发请求两次
3、重定向地址栏不会发⽣改变,请求转发地址栏会发⽣改变
4、重定向必须在⼀台服务器⾥进⾏,请求转发可以跨服务器进⾏
⚫ Cookie 和 Session 的区别
答:1、Cookie保存在浏览器中,Session保存在服务器中
2、Cookie不安全,Session相对⽐较安全
3、Cookie有⼤⼩限制,Session⽆⼤⼩限制
⚫ 说一说Servlet的生命周期?
servlet的生命周期分为三个阶段
1、初始化阶段,调用init()方法
2、相应客户请求阶段,调用service()方法
3、终止阶段,调用destroy()方法
⚫ 过滤器和拦截器的区别?
(1)拦截器是基于java的反射机制的,而过滤器是基于函数回调
(2)过滤器依赖于servlet容器,而拦截器不依赖于servlet容器
(3)拦截器只能对action请求起作用,而过滤器则可以对几乎所有的请求起作用
(4)拦截器可以访问action上下文、值栈里的对象,而过滤器不能
(5)在action的生命周期中,拦截器可以多次被调用,而过滤器只在容器初始化时调用一次
⚫ 监听器是什么?
Servlet监听器用于监听一些重要事件的发生,监听器对象可以在事情发生前、发生后可以做一些必要的处理。
1.Listener是Servlet的监听器
2.可以监听客户端的请求、服务端的操作等。
3.通过监听器,可以自动激发一些操作,如监听在线用户数量,当增加一个HttpSession时,给在线人数加1。
4.编写监听器需要实现相应的接口
5.编写完成后在web.xml文件中配置一下,就可以起作用了
6.可以在不修改现有系统基础上,增加web应用程序生命周期事件的跟踪
⚫ Filter生命周期?
服务器启动时会创建Filter实例,并且每个类型的Filter只创建一个实例,从此不再创建!在创建完Filter实例后,会马上调用init()方法完成初始化工作,这个方法只会被执行一次;每次用户访问目标资源的时候都会访问doFilter(),如果需要放行要调用FilteChain的doFilter(),如果不调用FilterChain的doFilter()方法,目标资源将无法被执行。服务器会在创建Filter对象之后,把Filter放到缓存中一直使用,通常不会销毁它。一般会在服务器关闭时销毁Filter对象,在销毁Filter对象之前,服务器会调用Filter对象的destory()方法。
⚫ session与cookie是如何交互的?
⚫ 如何防止表单重复提交?