1. 面向对象和面向过程的区别
- 一般来讲,面向过程性能较高,面向对象易维护、复用、扩展;
- java性能差的主要原因是 java 本身的语言特性(半编译)
补充:
- 解释性语言和编译型语言区别;
- jvm 是运行 java 字节码的虚拟机,目的是实现一次编译结果,可运行在不同系统,即平台无关性,生成相同的二进制机器码;
- java 可移植性:每种基本类型所占存储空间的大小不会随着机器硬件架构的变化而变化(也与 jvm 相关);
- JDK:创建 + 编译程序(javac、javadoc、jdb) + 包含 JRE-运行程序 (jvm、java类库、java命令、其他基础构件);
2. java 和 c++ 的区别
面向对象,支持封装、继承、多态;
- 程序内存安全:java 不提供通过指针直接访问内存;
- 类继承:java 类单继承(接口多继承), c++ 类多继承;
-
3. 字符型常量 和 字符串常量 的区别
形式:字符型常量-单引号+一个字符,字符串常量-双引号+多个字符;
- 含义:字符型常量相当于整型值,可直接参与运算,字符串常量代表该字符串在内存中的地址值;
-
4. 构造器 Constructor
不能被 override (继承),但可以 overload;
override 与 overload 的区别:
共同点:使用字符数组保存字符串;
- 可变性:String 用 final 修饰字符数组,StringBuffer、StringBuilder 无;
- 线程安全性:String(不变性)、StringBuffer(同步锁) 线程安全,StringBuilder 非线程安全;
- 性能:高->低(StringBuilder > StringBuffer > String(update 时 新对象,改引用));
多数情况下建议使用 StringBuilder 类,但在应用程序要求线程安全的情况下,必须使用 StringBuffer 类;
6. java 中无参 & 无实现构造方法的作用
执行子类构造方法前,若没有用super()来调用父类特定的构造方法,则会调用父类中无参的构造方法;
7. import java 和 javax 的区别
-
8. 成员变量与局部变量的区别
语法形式:成员变量属于类,局部变量是在方法中定义的变量或是方法的参数;
- 修饰符:只有成员变量可被 public,private,static 等修饰,成员变量和局部变量都能被 final 所修饰;
- 存储:有 static 修饰的成员变量属于类,否则属于实例(堆内存),局部变量(栈内存);
- 生存周期:成员变量随着对象的创建而存在,局部变量随着方法的调用而自动消失;
初值:成员变量有自动默认值(final 修饰的成员变量必须显式赋值),局部变量需手动赋值;
9. 对象实体与对象引用的区别
一个对象引用可以指向0个或1个对象,一个对象可以有n个引用指向它;
10. 静态方法和实例方法的区别
外部调用:类名 or 对象.静态方法,对象.实例方法;
-
11. == 与 equals 的区别
==:基本数据类型比较值,引用数据类型比较内存地址;
- equals:类如果没有重写 equals(),则等价于“==”,否则以 equals() 方法比较两个对象是否相等;
String 类已重写 equals 方法;
public class testEquals {
public static void main(String[] args){
testEquals();
}
public static void testEquals(){
String a = new String("cyt");//引用
String b = new String("cyt");//引用
String c = "cyt";//字符串常量
String d = "cyt";
if (a == b) { System.out.println("a == b"); }//false 对比的是两个对象的地址
if (a.equals(b)) { System.out.println("a equals b"); }//true
if (c == d) { System.out.println("c == d"); }//true
if (c.equals(d)) { System.out.println("c equals d"); }//true
Person p1 = new Person("cyt");
Person p2 = new Person("cyt");
if (p1 == p2) { System.out.println("p1 == p2"); }//false
if (p1.equals(p2)) { System.out.println("p1 equals p2"); }//无重写equals方法时,为false,否则,为true
}
}
class Person{
private String name;
public Person(){}
public Person(String name){ this.name = name;}
public String getName() {return name;}
public void setName(String name) { this.name = name;}
@Override
public boolean equals(Object p){
if (p instanceof Person) {
if (this.getName().equals(((Person) p).getName())) {
return true;
}
}
return false;
}
}
12. hashCode() 与 equals()
- 判断重复:先判断 hashCode 是否相同,若相同则调用 equals()方法,若两个对象相等,则equals方法返回true;
- hashcode 相同是对象相同的必要不充分条件;
equals 方法被覆盖,则 hashCode 方法也必须被覆盖;
13. Java 无引用传递,只有值传递
一个方法不能修改一个基本数据类型的参数(即数值型或布尔型);
- 一个方法可以改变一个对象参数的状态;
- 一个方法不能让对象参数引用一个新的对象;
public class testValueTransit {
public static void main(String[] args){
caseOneMain();
caseTwoMian();
caseThreeMian();
}
public static void caseOneMain(){
int num1 = 3, num2 = 5;
System.out.println("num1 = " + String.valueOf(num1) + " , num2 = " + String.valueOf(num2));
oneSwap(num1, num2);
//输出 :num1 = 3 , num2 = 5 ;num1 = 5 , num2 = 3
}
public static void oneSwap(int num1, int num2){
int tmp;
tmp = num1; num1 = num2; num2 = tmp;
System.out.println("num1 = " + String.valueOf(num1) + " , num2 = " + String.valueOf(num2));
}
public static void caseTwoMian(){
Person p = new Person("cyt");
System.out.println("original name is : " + p.getName());
System.out.println("point new person : " + twoUpdate(p).getName());
System.out.println("updated name is : " + p.getName());
/** 输出
original name is : cyt
point new person : zgx
updated name is : beauty
**/
}
public static Person twoUpdate(Person p1){
p1.setName("beauty");
p1 = new Person("zgx");
return p1;
}
public static void caseThreeMian(){
Person p1 = new Person("cyt");
Person p2 = new Person("zgx");
threeSwap(p1, p2);
System.out.println("p1's name is " + p1.getName() + " , p2's name is " + p2.getName());
/** 输出
p1's name is zgx , p2's name is cyt
p1's name is cyt , p2's name is zgx
**/
}
public static void threeSwap(Person p1, Person p2){
Person p;
p = p1; p1 = p2; p2 = p;
System.out.println("p1's name is " + p1.getName() + " , p2's name is " + p2.getName());
}
}
14. final 关键字
- 修饰变量:初始化后,基本数据类型的变量不能修改,引用类型的变量不能指向另一个对象,即 final 型对象引用不可修改,但是其引用的值如果不是final型可以修改;;
- 修饰类:类不能继承,其所有成员方法被隐式地被指定为 final;
- 修饰方法:1)防止继承类修改该方法(类中所有 private 方法都隐式地指定为 final);
- 注意:
- 父类的 private 成员方法不能被子类方法覆盖,其默认是final类型;
- 数组是一种特殊的对象类型; ```java import java.util.Arrays; import java.util.List; import java.util.stream.Collectors;
public class testKeyFinal {
private final int a = 3;
private String b = “variable”;
private Person p1 = new Person(“normal_person”);
private final Person p2 = new Person(“final_person”);
private int[] arr_1 = {1,2,3,4,5};
private final List
public static void main(String[] args){
testFinalData();
testKeyFinal.SubClass.testFinalMemberFun();
}
public static void testFinalData(){
testKeyFinal finalData = new testKeyFinal();
//*------------------------基础类型测试--------------------------*
// finalData.a = 10; 常量,无法修改
finalData.b = “cyt”;
System.out.println(“final 作用于 基础数据类型:” + String.valueOf(finalData.a) + “ 、”+finalData.b);//final 作用于 基础数据类型:3 、cyt
//————————————对象类型测试—————————————
finalData.p1 = new Person(“normal_cyt”);
finalData.p2.setName(“update_final_person”);
System.out.println(finalData.p1.getName() + “ “ + finalData.p2.getName());//normal_cyt update_final_person
// finalData.p2 = new Person(“final_cyt”); // final 型对象引用不可修改,但是其引用的值如果不是final型可以修改;
//————————————数组类型测试—————————————
finalData.arr_1 = new int[2];
// finalData.arr_2 = new int[10]; // 数组是一种特殊的对象类型
List
}
public static final void testFinalClass(){
System.out.println("父类的final方法");
}
public static void testFinalMemberFun(){
System.out.println("父类的非final方法 testFinalClass");
}
static class SubClass extends testKeyFinal{
public static void testFinalMemberFun(){
System.out.println("父类的 static final 变量:" + VALUE_ONE);
System.out.println("继承类可以重写父类的非final方法 testFinalClass");
}
// public static void testFinalClass(){} //继承类不能重写父类的final方法 } // static class subClass1 extends FinalClass{ // // }//final 类不能被继承,final 的成员方法没有机会被覆盖,默认都是 final 的 } final class FinalClass{ void func(){ System.out.println(“hello”); } }
<a name="EAM16"></a>
## 15. static 关键字
- 静态成员变量和成员方法:属于类,被类的所有对象共享,一般通过类名调用;
- 静态代码块:定义在类中方法外,执行顺序:静态代码块(只执行一次)—>非静态代码块—>构造方法(后两个在生成新对象自动调用);
- 静态内部类: 创建不依赖于外围类,不能直接使用外围类的非 static 成员变量和方法;
- 静态导包:import static + 指定类,直接导入静态资源,无需通过类名调用静态成员;
- 其他
- 静态成员变量不能用 private 修饰;
- 非静态内部类中不能定义静态变量;
- 静态代码块
* 定义:可定义多个,可放在类成员方法外的任意位置;<br /> * 执行:仅执行一次,执行优先顺序为 静态代码块>普通代码块>构造函数,(普通代码块和构造函数会随 生成对象执行多次),同级按定义顺序执行;<br /> * 可为静态成员变量赋值,但不能访问;<br /> * 代码块的一般作用是对类的一些 static 变量进行赋值,常用于不需要创建对象就可以调用类中的方法;
- 不能直接调用静态内部类的非静态变量或非静态成员方法,需通过外部对象调用;
- 静态内部类
- 静态内部类的创建不依赖于外围类,内部不能使用外围类的非 static 成员变量和方法;
- 外围类可直接调用其静态成员变量或方法,可通过实例化静态内部类获取其非静态成员;
- 补充:
- [java 常见代码块的作用与区别](https://blog.csdn.net/Dustin_CDS/article/details/79143760)
- [内部类学习](https://www.cnblogs.com/chenssy/p/3388487.html)
```java
public class testKeyStatic {
public static void main(String[] args){
testStatic();
}
public static void testStatic(){
// 静态成员变量、成员方法
Student.classNum = 2;
for (int i = 0; i < 3; i++) {
Student s = new Student(String.valueOf(i));
s.sayHello(s);
Student.classNum += i;
System.out.println(s);
}
System.out.println("final classNum : " + Student.classNum);
Student.sayHello();
// 静态代码块
// 静态内部类(对比非静态 内部类进行学习)
Student.displayInnerClass();
// 静态导包
System.out.println("test 静态导包, 调用 Math 中的 max 函数: max(123, 4) = " + String.valueOf(max(123,4)));
}
}
class Student{
static {
System.out.println("just test 静态代码块 start");
}
static {
classNum = 2;
System.out.println("just test 静态代码块 sleep");
// System.out.println(classNum); // 只可以对静态成员变量赋值,不可以访问
}
static class Learn{
public static String course = "Java";
public String flag = "hard";
public void disPlay(){
System.out.println(classNum);//可直接访问外部内的静态成员变量
Student.sayHello();
System.out.println(new Student("cyt").getName()); // 因为新建对象 cyt ,所以会调用普通代码块
}
}
class Play{
// public static String fun = "singing"; // 不能定义静态变量
public void disPlay(){
System.out.println(classNum); //可调用外围类的任何成员
System.out.println(name);
sayHello();
}
}
private String name;//非静态成员变量不能被静态代码块访问
static Integer classNum; // 不能用private
public Student() {}
{
System.out.println("just test 普通代码块");
}
public Student(String name) { this.name = name;}
public String getName() { return name;}
public void setName(String name) { this.name = name;}
public static void sayHello(Student s){
System.out.println("Just test static function: " + classNum + ", name = " + s.getName());
}
public static void sayHello(){
System.out.println("Just test static function: " + classNum);
}
public static void displayInnerClass(){
System.out.println("**********************************");
System.out.println("test staticInnerClass : " + Learn.course);//不能直接调用静态内部类的非静态变量,需实例化new Learn().flag
new Learn().disPlay();
System.out.println("**********************************");
System.out.println("test normalInnerClass" );
Play play = new Student().new Play();//必须通过外围类定义,此处生成了一个空对象,依然会调用普通代码块,而且name=null
play.disPlay();
}
@Override
public String toString(){
return "the student's name is " + this.name + " , and the total classNum : " + classNum;
}
static {
System.out.println("just test 静态代码块 end");
}
}
输出:
/** 运行结果:
* just test 静态代码块 start
* just test 静态代码块 sleep
* just test 静态代码块 end
* just test 普通代码块
* Just test static function: 2, name = 0
* the student's name is 0 , and the total classNum : 2
* just test 普通代码块
* Just test static function: 2, name = 1
* the student's name is 1 , and the total classNum : 3
* just test 普通代码块
* Just test static function: 3, name = 2
* the student's name is 2 , and the total classNum : 5
* final classNum : 5
* Just test static function: 5
* **********************************
* test staticInnerClass : Java
* 5
* Just test static function: 5
* just test 普通代码块
* cyt
* **********************************
* test normalInnerClass
* just test 普通代码块
* 5
* null
* Just test static function: 5
* test 静态导包, 调用 Math 中的 max 函数: max(123, 4) = 123
*/
16. 内部类
- 特性
- 内部类可以有多个实例,每个实例都有自己的状态信息,并且与其他外围对象的信息相互独立;
- 在单个外围类中,可以让多个内部类以不同的方式实现同一个接口,或者继承同一个类(解决继承类和接口时的命名冲突,或实现多继承);
- 创建内部类对象的时刻并不依赖于外围类对象的创建(静态内部类);
- 内部类并没有令人迷惑的 “is-a” 关系,ta 就是一个独立的实体;
- 内部类提供了更好的封装,除了该外围类,其他类都不能访问;
- 优势
- 可访问外部类的私有成员(属性、方法);
- 用内部类定义在外部类中不可访问的属性,在外部类中实现比外部类的 private 更小的访问权限;
- 注:内部类是一个编译时的概念,一旦编译成功,就会成为两个完全不同的类;
- 分类:成员内部类、局部内部类、匿名内部类、静态内部类;
- 除静态内部类外,成员内部类与局部内部类需满足:
- 不能存在任何 static 的变量和方法;why 【生命周期不一致】
- 依附于外围类,只有创建外围类后才能创建内部类;
- 内部类对外部类的调用无差别,即与修饰无关,包括 private 、 static 等;
- 内部类调用外部类变量、方法:同名下采用类名.this.变量/方法,不同名直接调用;
- 外部类调用内部变量、方法:
- 外部类的非 static 方法:创建 内部类对象;
- 外部类的 static 方法:与在外部类访问成员内部类一样,需先创建一个外部类,再创建内部类;
- 静态内部类的限制:只能直接调用外部类的静态属性和方法;
匿名内部类的特性 详见
- 非抽象,使用匿名内部类时只能继承一个类或实现一个接口;
- 不能定义构造函数,使用构造代码块初始化匿名内部类;
- 包含于局部内部类,受其所有限制,其中 方法传递到内部类的形参必须是 final 类型,jdk 1.8 已智能实现;
- 匿名内部类只能使用一次;
常用于 多线程; ```java public class testInnerClass { public static void main(String[] args){ Outer outer = new Outer(); testInnerMemberClass(outer); // testStaticInnerClass();// 静态内部类必须依赖于外部类的创建 // testPartInnerClass(outer); // testAnonymous();
} public static void testInnerMemberClass(Outer outer){ /** Summaries
* 1. 成员内部类不可定义静态变量或方法; * 2. 成员内部类对外部类的调用无差别(与修饰无关,private、static 等); * 3. 同名变量,内部调外部直接用 - 类名.this.变量,外部调内部需生成内部对象; * 4. 外部非静态类调用内部类,只需直接创建内部类,而外部类静态方法调用内部类,与在外部类访问成员内部类一样; */
Outer.static_value = “smile”; outer.func3(); outer.func(); /**OutPut
* *************外部类调用成员内部类的成员变量和函数************ * 成员内部类同名变量: 3, 外部类同名变量: 9 * 成员内部类生成对外部类的引用:smile * *************成员内部类调用外部类的成员变量和函数************ * 外部类同名变量: 9, 成员内部类同名变量: 3 * 外部类不同名变量: cyt * 外部类静态变量: smile * test outer func1 * test outer func2 */
} public static void testStaticInnerClass(){ /**Summaries
* 1. 静态内部类只能调用外部类的静态成员或变量; * 2. 静态内部类自己实现变量或方法定义自由(可用 static 修饰); * 3. 静态内部类不可用 private 修饰; */
Outer.static_value = “outer_static_value”; Outer.func4(); /**Output
* *************外部类调用静态内部类的成员变量和函数************ * 静态内部类同名非静态变量: same_staticValue, 外部类同名静态变量: outer_static_value * 直接通过类名调用静态内部类的静态成员变量: StaicInner.cyt * *************静态内部类调用外部类的成员变量和函数************ * 外部类同名静态变量: outer_static_value, 静态内部类同名非静态变量: same_staticValue * 静态内部类的静态变量: StaicInner.cyt, 静态内部类的非静态变量: 5 */
} public static void testPartInnerClass(Outer outer){ outer.func5(“part_value”); }
public static void testAnonymous(){ final int k = 3; //创建匿名类的时候,必须实现接口或抽象父类中的所有抽象方法,必要时甚至可以重写父类中的普通方法。 new Animal() {
{ System.out.println("匿名内部类的初始化只能通过代码块(因为匿名所以无构造函数)"); this.setFood("bambo"); } public void func1(int k){ System.out.println(this.getFood()); System.out.println("匿名内部类自定义方法"); eat(k); } @Override public void eat(int innner_k) { System.out.println(innner_k); }
}.func1(k); // 继承一个类 // Thread t = new Thread(){ // public void run(){ // for (int i = 0; i <= 10; i++) { // System.out.println(i + “ “); // } // } // }.start(); // 实现一个接口 // Runnable r = new Runnable() { // @Override // public void run() { // for (int i = 0; i <= 10; i++) { // System.out.println(i + “ “); // } // } // }; // Thread t = new Thread(r); // t.start(); } } abstract class Animal{ private String food;
public String getFood() { return food; }
public void setFood(String food) { this.food = food; }
public Animal(){}//抽象类可以有构造函数 public abstract void eat(int k); public void play(){ System.out.println(“just have fun”); } } class Outer{ private int i = 9; private String j = “cyt”; // final Long m = 9L; static String static_value; public Outer(){} public static void func(){ Outer outer = new Outer(); Inner inner = outer.new Inner(); inner.outerStaticFunc(); } public static void func1(){ System.out.println(“test outer func1”); } public void func2(){ System.out.println(“test outer func2”); } public void func3(){ //外部非静态类调用内部类,只需直接创建内部类,而外部类静态方法调用内部类,与在外部类访问成员内部类一样 System.out.println(“*外部类调用成员内部类的成员变量和函数**“); Inner inner = new Inner(); System.out.println(“成员内部类同名变量: “ + String.valueOf(inner.i) + “, 外部类同名变量: “ + i); System.out.println(“成员内部类生成对外部类的引用:” + inner.referOuter().static_value); inner.innerFun(); } public static void func4(){ System.out.println(“*外部类调用静态内部类的成员变量和函数**“); Outer.StaicInner staicInner = new Outer.StaicInner(); System.out.println(“静态内部类同名非静态变量: “ + staicInner.static_value + “, 外部类同名静态变量: “ + static_value); System.out.println(“直接通过类名调用静态内部类的静态成员变量: “ + Outer.StaicInner.j); staicInner.StaicInnerFun1(); } public void func5(String out_value){ System.out.println(“*外部类成员函数调用局部内部类**“); // 局部内部类与成员内部类一样被编译,只是其作用域发生了改变,只能在该方法中被使用 class PartInner{
private int inner_i = 2; private String j = "partInner_cyt";
// static int a;//can’t define any static variable
PartInner(String out_value){ partInnerFunc1(out_value); } void partInnerFunc1(String out_value){ System.out.println("外部类同名变量: " + String.valueOf(Outer.this.j) + ", 局部内部类同名变量: " + this.j); System.out.println("外部类不同名静态变量: " + static_value); //外部类不同名变量直接获取,此处静态变量未初始化,所以为null; System.out.println("外部类的局部变量(即方法内变量)需用 final 修饰: " + out_value);//java 1.8 已智能实现 }
} new PartInner(out_value); } private class Inner{//成员内部类可以用 public、private、protected 修饰 private int i = 3; // private static int inner_i;//内部类不能定义静态变量 int inner_j = 1; Inner(){} Inner(int i, int inner_j){
this.i = i; this.inner_j = inner_j;
} void dealOuter(){
System.out.println("*************成员内部类调用外部类的成员变量和函数************"); // 外部类同名变量可采用 外部类名.this.变量 获取,内部类同名变量可直接获取或通过 this.变量 System.out.println("外部类同名变量: " + String.valueOf(Outer.this.i) + ", 成员内部类同名变量: " + i); System.out.println("外部类不同名变量: " + j); //外部类不同名变量直接获取 System.out.println("外部类静态变量: " + static_value); func1(); func2(); //内部类调用外部类的非同名变量或方法,无关修饰,包括 private 、static 等
} // static void innerFun(){ }//内部类不能定义静态方法 private void innerFun(){
dealOuter();
} private void outerStaticFunc(){
System.out.println("外部类静态方法调用内部类需创建外部类,然后再创建内部类");
} private Outer referOuter(){
return Outer.this;// 创建外部类的引用
} } public static class StaicInner{//静态内部类不能用 private 修饰,这点相当于静态变量; private int i = 5; static String j = “StaicInner.cyt”; public String static_value = “same_staticValue”; void StaicInnerFun1(){
System.out.println("*************静态内部类调用外部类的成员变量和函数************"); System.out.println("外部类同名静态变量: " + Outer.static_value + ", 静态内部类同名非静态变量: " + static_value); System.out.println("静态内部类的静态变量: " + j + ", 静态内部类的非静态变量: " + i);
} }
} ```