Java面试题库:Java基础(一)
相同之处:都是分支语句,对超过一种的情况进行判断处理。
不同之处:switch更适合用于多分支情况,就是有很多种情况需要判断处理,判断条件类型单一,只有一个入口,在分支执行完后(如果没有break跳出),不加判断地执行下去;而if—elseif---else多分枝主要适用于分支较少的分支结构,判断类型不是单一,只要一个分支被执行后,后边的分支不再执行。switch为等值判断(不允许比如>= <=),而if为等值和区间都可以,if的使用范围大。
while先判断后执行,第一次判断为false,循环体一次都不执行
do while先执行 后判断,最少执行1次。
break: 结束当前循环并退出当前循环体。break还可以退出switch语句
continue: 循环体中后续的语句不执行,但是循环没有结束,继续进行循环条件的判断(for循环还会i++)。continue只是结束本次循环。
package com.geekshow; import java.io.File;
public class $ {public static void main(String[] args) {
String path = "D:/301SXT";
test(path);
}
private static void test(String path) { File f = new File(path); File[] fs = f.listFiles(); if (fs == null) { return; } for (File file : fs) { if (file.isFile()) { System.out.println(file.getPath()); } else { test(file.getPath()); } } }
递归就是在过程或函数里调用自身。
在使用递归策略时,必须有一个明确的递归结束条件,称为递归出口。
递归算法解题通常显得很简洁,但运行效率较低。所以一般不提倡用递归算法设计程序。
在递归调用的过程当中系统为每一层的返回点、局部量等开辟了栈来存储。递归次数过多容易造成栈溢出等。所以一般不提倡用递归算法设计程序。
package com.geekshow;
public class TestBubbleSort {
public static void sort(int[] a) {
int temp = 0;
// 外层循环,它决定一共走几趟
for (int i = 0; i <a.length-1; ++i) {
//内层循环,它决定每趟走一次
for (int j = 0; j <a.length-i-1 ; ++j) {
//如果后一个大于前一个
if (a[j + 1] < a[j]) {
//换位
temp = a[j];a[j] = a[j + 1];a[j + 1] = temp;
}
}
}
public static void sort2(int[] a) {
int temp = 0;
for (int i = 0; i <a.length-1; ++i) {
//通过符号位可以减少无谓的比较,如果已经有序了,就退出循环
int flag = 0;
for (int j = 0; j <a.length-1-i ; ++j) {
if (a[j + 1] < a[j]) {
temp = a[j];
a[j] = a[j + 1];
a[j + 1] = temp;
flag = 1;
}
}
if(flag == 0){
break;
}
}
}
}
package com.geekshow;
public class TestSelectSort {
public static void sort(int arr[]) {
int temp = 0;
for (int i = 0; i < arr.length - 1; i++) {
// 认为目前的数就是最小的, 记录最小数的下标
int minIndex = i;
for (int j = i + 1; j < arr.length; j++) {
if (arr[minIndex] > arr[j]) {
// 修改最小值的下标
minIndex = j;
}
}
// 当退出for就找到这次的最小值
if (i != minIndex) {
temp = arr[i];
arr[i] = arr[minIndex];
arr[minIndex] = temp;
}
}
}
}
package com.geekshow;
public class TestInsertSort {
public static void sort(int arr[]) {
int i, j;
for (i = 1; i < arr.length; i++) {
int temp = arr[i];
for (j = i; j > 0 && temp < arr[j - 1]; j--) {
arr[j] = arr[j - 1];
}
arr[j] = temp;
}
}
}
可变参数的形式 ...
可变参数只能是方法的形参
可变参数对应的实参可以0,1,2.....个,也可以是一个数组
在可变参数的方法中,将可变参数当做数组来处理
可变参数最多有一个,只能是最后一个
可变参数好处:方便 简单 减少重载方法的数量
如果定义了可变参数的方法,不允许同时定义相同类型数组参数的方法
实参都可以是数组;
方法体中,可变参数当做数组来处理
个数不同 可变参数只能有一个数组参数可以多个
位置不同 可变参数只能是最后一个 数组参数位置任意
实参不同 可变参数实参可以0,1,2.....个,也可以是一个数组,数组的实参只能是数组
类是对象的抽象,而对象是类的具体实例。类是抽象的,不占用内存,而对象是具体的,占用存储空间。类是用于创建对象的蓝图,它是一个定义包括在特定类型的对象中的方法和变量的软件模板。
类和对象好比图纸和实物的关系,模具和铸件的关系。
比如人类就是一个概念,人类具有身高,体重等属性。人类可以做吃饭、说话等方法。小明就是一个具体的人,也就是实例,他的属性是具体的身高200cm,体重180kg,他做的方法是具体的吃了一碗白米饭,说了“12345”这样一句话。
两者都是软件开发思想,先有面向过程,后有面向对象。在大型项目中,针对面向过程的不足推出了面向对象开发思想。
蒋介石和毛泽东分别是面向过程和面向对象的杰出代表,这样充分说明,在解决复制问题时,面向对象有更大的优越性。
面向过程是蛋炒饭,面向对象是盖浇饭。盖浇饭的好处就是“菜”“饭”分离,从而提高了制作盖浇饭的灵活性。饭不满意就换饭,菜不满意换菜。用软件工程的专业术语就是“可维护性”比较好,“饭” 和“菜”的耦合度比较低。
编程思路不同:面向过程以实现功能的函数开发为主,而面向对象要首先抽象出类、属性及其方法,然后通过实例化类、执行方法来完成功能。
封装性:都具有封装性,但是面向过程是封装的是功能,而面向对象封装的是数据和功能。
面向对象具有继承性和多态性,而面向过程没有继承性和多态性,所以面向对象优势是明显。
方法重载和方法重写(覆盖)的区别
this是对象内部指代自身的引用,同时也是解决成员变量和局部变量同名问题;this可以调用成员变量,不能调用局部变量;this也可以调用成员方法,但是在普通方法中可以省略this,在构造方法中不允许省略,必须是构造方法的第一条语句。,而且在静态方法当中不允许出现this关键字。
super代表对当前对象的直接父类对象的引用,super可以调用直接父类的成员变量(注意权限修饰符的影响,比如不能访问private成员)
static可以修饰变量、方法、代码块和内部类
static属性属于这个类所有,即由该类创建的所有对象共享同一个static属性。可以对象创建后通过对象名.属性名和类名.属性名两种方式来访问。也可以在没有创建任何对象之前通过类名.属性名的方式来访问。
在内存中份数不同
不管有多少个对象,static变量只有1份。对于每个对象,实例变量都会有单独的一份
static变量是属于整个类的,也称为类变量。而非静态变量是属于对象的,也称为实例变量
在内存中存放的位置不同
访问的方式不同
实例变量:对象名.变量名 stu1.name="小明明";
静态变量:对象名.变量名 stu1.schoolName="西二旗小学"; 不推荐如此使用
类名.变量名 Student.schoolName="东三旗小学"; 推荐使用
在内存中分配空间的时间不同
Student.schoolName="东三旗小学";或者Student stu1 = new Student("小明","男",20,98);
static方法也可以通过对象名.方法名和类名.方法名两种方式来访问
static代码块。当类被第一次使用时(可能是调用static属性和方法,或者创建其对象)执行静态代码块,且只被执行一次,主要作用是实现static属性的初始化。
static内部类:属于整个外部类,而不是属于外部类的每个对象。不能访问外部类的非静态成员(变量或者方法),.可以访问外部类的静态成员
final和abstract是功能相反的两个关键字,可以对比记忆
final可以用来修饰类、方法和属性,不能修饰构造方法。使用final修饰的类不能被继承,使用final修饰的方法不能被重写,使用final修饰的变量的值不能被修改,所以就成了常量。
特别注意:final修饰基本类型变量,其值不能改变,由原来的变量变为常量;但是final修饰引用类型变量,栈内存中的引用不能改变,但是所指向的堆内存中的对象的属性值仍旧可以改变。例如
package com.geekshow;
class Test {
public static void main(String[] args) {
final Dog dog = new Dog("欧欧");
dog.name = "美美";//正确
dog = new Dog("亚亚");//错误
}
}
十六、final、finally、finalize的区别
final修饰符(关键字)如果一个类被声明为final,意味着它不能再派生出新的子类,不能作为父类被继承例如:String类、Math类等。将变量或方法声明为final,可以保证它们在使用中不被改变。被声明为final的变量必须在声明时给定初值,而在以后的引用中只能读取,不可修改。被声明为final的方法也同样只能使用,不能重写,但是能够重载。使用final修饰的对象,对象的引用地址不能变,但是对象的值可以变!
finally在异常处理时提供 finally 块来执行任何清除操作。如果有finally的话,则不管是否发生异常,finally语句都会被执行。一般情况下,都把关闭物理连接(IO流、数据库连接、Socket连接)等相关操作,放入到此代码块中。
finalize方法名。Java 技术允许使用 finalize() 方法在垃圾收集器将对象从内存中清除出去之前做必要清理工作。finalize() 方法是在垃圾收集器删除对象之前被调用的。它是在 Object 类中定义的,因此所有的类都继承了它。子类覆盖 finalize() 方法以整理系统资源或者执行其他清理工作。一般情况下,此方法由JVM调用,程序员不要去调用!
public boolean equals(java.lang.Object)
public native int hashCode() 获取哈希码
public java.lang.String toString() 把数据转变成字符串
public final native java.lang.Class getClass() 获取类结构信息
protected void finalize() throws java.lang.Throwable
protected native Object clone() throws
public final void wait() throws java.lang.InterruptedException
public final native void notify() 多线程中唤醒功能
public final native void notifyAll() 多线程中唤醒所有等待线程的功能
public公共的 可被同一项目中所有的类访问。(必须与文件名同名)
default默认的 可被同一个包中的类访问。
public 公共的 可以被项目中所有的类访问。(项目可见性)
protected 受保护的 可以被这个类本身访问;同一个包中的所有其他的类访问;被它的子类(同一个包以及不同包中的子类)访问。(子类可见性)
default 默认的被这个类本身访问;被同一个包中的类访问。(包可见性)
private 私有的 只能被这个类本身访问。(类可见性)
情况1:如果子类的构造方法中没有通过super显式调用父类的有参构造方法,也没有通过this显式调用自身的其他构造方法,则系统会默认先调用父类的无参构造方法。在这种情况下,写不写“super();”语句,效果是一样的。
情况2:如果子类的构造方法中通过super显式调用父类的有参构造方法,那将执行父类相应构造方法,而不执行父类无参构造方法。
情况3:如果子类的构造方法中通过this显式调用自身的其他构造方法,在相应构造方法中应用以上两条规则。
特别注意的是,如果存在多级继承关系,在创建一个子类对象时,以上规则会多次向更高一级父类应用,一直到执行顶级父类Object类的无参构造方法为止。
基本类型,比较的是值
引用类型,比较的是地址
不能比较没有父子关系的两个对象
系统类一般已经覆盖了equals(),比较的是内容。
用户自定义类如果没有覆盖equals(),将调用父类的equals (比如是Object),而Object的equals的比较是地址(return (this == obj);)
用户自定义类需要覆盖父类的equals()
标签:
上一篇: Java面试题库:Java基础(二)
下一篇: Mysql 连接数,最大并发数设置