13、数组的初始化
一维数组:
- int[] arr = new int[]{1,2,3,4,5}; //正确
- int[] arr = {1,2,3,4,5}; //正确
- int[] arr = new int[5]{1,2,3,4,5}; //错误
- int[] arr;
- arr = new int[]{1,2,3,4,5}; //正确。
- arr = {1,2,3,4,5}; //错误
二维数组:
- int[][] arr = new int[3][2]; //正确
- int[] arr[] = new int[3][2]; //正确
- int arr[][] = new int[3][2]; //正确
14、值传递和引用传递
- 值传递:传递的是值的拷贝,不改变原值。如基本数据类型及其包装类、String。
- 引用传递:传递的是引用的地址值,改变原值。如类类型,接口类型和数组。
- Java中只有传值,因为地址值也是值。(面试)
15、static关键字
- static关键字的特点
- 随着类的加载而加载
- 优先于对象存在
- 被类的所有对象共享
- 可以通过类名调用
- static的注意事项
- 在静态方法中是没有this关键字的
- 如何理解呢?
- 静态是随着类的加载而加载,this是随着对象的创建而存在。
- 静态比对象先存在。
- 如何理解呢?
- 静态方法只能访问静态的成员变量和静态的成员方法
- 简单记:
- 静态只能访问静态。
- 简单记:
- 在静态方法中是没有this关键字的
- 如果一个类中所有的方法都是静态的(工具类),需要私有化构造方法,目的是不让其他类创建本类对象。
16、代码块的概述和分类(面试)
- 代码块概述
- 在Java中,使用{}括起来的代码被称为代码块。
- 代码块分类
- 根据其位置和声明的不同,可以分为局部代码块,构造代码块,静态代码块,同步代码块(多线程)。
- 常见代码块的应用
- 局部代码块
- 在方法中出现;限定变量生命周期,及早释放,提高内存利用率
- 构造代码块 (初始化块)
- 在类中方法外出现;多个构造方法方法中相同的代码存放到一起,每次调用构造都执行,并且在构造方法前执行
- 静态代码块
- 在类中方法外出现,并加上static修饰;用于给类进行初始化,在加载的时候就执行,并且只执行一次。
- 一般用于加载驱动
- 局部代码块
面试题:看程序写结果
class Student { static { System.out.println("Student 静态代码块"); } { System.out.println("Student 构造代码块"); } public Student() { System.out.println("Student 构造方法"); } } class Demo2_Student { static { System.out.println("Demo2_Student静态代码块"); } public static void main(String[] args) { System.out.println("我是main方法"); Student s1 = new Student(); Student s2 = new Student(); } } 结果: Demo2_Student静态代码块 我是main方法 Student 静态代码块 Student 构造代码块 Student 构造方法 Student 构造代码块 Student 构造方法
17、开发的原则
- 高内聚,低耦合
- 耦合:类与类的关系
- 内聚:就是自己完成某件事情的能力
18、继承的注意事项
- 子类只能继承父类所有非私有的成员(成员方法和成员变量)
- 子类不能继承父类的构造方法,但是可以通过super关键字去访问父类构造方法。
- 子类中所有的构造方法默认都会访问父类中空参数的构造方法
- 因为子类会继承父类中的数据,可能还会使用父类的数据。
- 所以,子类初始化之前,一定要先完成父类数据的初始化。
- 其实:每一个构造方法的第一条语句默认都是:super(),Object类是最顶层的父类。
- 当类没有重载有参数的构造方法,JVM会默认增加一个空参数的构造方法。否则,不增加。
面试题
看程序写结果1: class Fu{ public int num = 10; public Fu(){ System.out.println("fu"); } } class Zi extends Fu{ public int num = 20; public Zi(){ System.out.println("zi"); } public void show(){ int num = 30; System.out.println(num); System.out.println(this.num); System.out.println(super.num); } } class Test1_Extends { public static void main(String[] args) { Zi z = new Zi(); z.show(); } } 结果: fu zi 30 20 10 看程序写结果2 class Fu { static { System.out.println("静态代码块Fu"); } { System.out.println("构造代码块Fu"); } public Fu() { System.out.println("构造方法Fu"); } } class Zi extends Fu { static { System.out.println("静态代码块Zi"); } { System.out.println("构造代码块Zi"); } public Zi() { System.out.println("构造方法Zi"); } } public class Demo{ public static void main(String[] args) { Zi z = new Zi(); } } /* * 1、JVM先加载Fu.class,加载后执行Fu静态代码块,然后再加载Zi.class,加载后执行Zi静态代码块。 * 2、在执行Zi.class的构造方法之前先执行Fu.class的构造方法 * 3、执行构造方法之前先执行构造代码块 */ 结果: 静态代码块Fu 静态代码块Zi 构造代码块Fu 构造方法Fu 构造代码块Zi 构造方法Zi
19、this和super的区别
- this和super都代表什么
- this:代表当前对象的引用,谁来调用我,我就代表谁
- super:代表当前对象父类的引用
- this和super的使用区别
- 调用成员变量
- this.成员变量 调用本类的成员变量,也可以调用父类的成员变量
- super.成员变量 调用父类的成员变量
- 调用构造方法
- this(…) 调用本类的构造方法
- super(…) 调用父类的构造方法
- 调用成员方法
- this.成员方法 调用本类的成员方法,也可以调用父类的方法
- super.成员方法 调用父类的成员方法
- 调用成员变量
- 注意,super(…)或者this(….)必须出现在构造方法的第一条语句上
20、方法重载、方法覆盖、多态
方法重载(Overload):方法名相同,参数不同。
void foo(String str); void foo(int number);
方法覆盖(Override):也叫方法重写,父类与子类有同样的方法名和参数。
class Parent { void foo() { System.out.println("Parent foo()"); } } class Child extends Parent { void foo() { System.out.println("Child foo()"); } }
- 多态:见下21
21、多态
- 概述
- 事物存在多种形态
多态的前提:
- 要有继承关系
- 要有方法重写(覆盖)
要有父类引用指向子类对象(调用方法时会调用子类的实现,而不是父类的实现)
Parent instance = new Child(); instance.foo(); // Child foo()
多态中成员访问特点
- 成员变量:调用变量时会调用父类的变量
- 成员方法:调用方法时会调用子类的实现
静态方法:调用方法时会调用父类的实现(静态与类相关,算不上重写)
public class Demo{ public static void main(String[] args) { Father f = new Son(); System.out.println(f.num); f.print(); f.method(); } } class Father { int num = 10; public void print(){ System.out.println("father"); } public static void method(){ System.out.println("father static method"); } } class Son extends Father{ int num = 20; public void print(){ System.out.println("son"); } public static void method(){ System.out.println("son static method"); } } 结果: 10 son father static method
- 多态的好处
- 提高了代码的维护性(继承保证)
- 提高了代码的扩展性(由多态保证)
- 可以作为形式参数,接受任意子类对象
- 多态的弊端
- 不能使用子类特有的属性和行为
22、方法重写的注意事项
- 父类中私有方法不能被重写
- 因为父类私有方法子类根本就无法继承
- 子类重写父类方法时,访问权限不能更低
- 最好就一致
- 父类静态方法,子类也必须通过静态方法进行重写
- 静态与类相关,其实算不上重写。
23、final关键字
- final修饰特点
- 修饰类,类不能被继承
- 修饰变量,变量就变成了常量,只能被赋值一次
- 修饰方法,方法不能被重写
- final关键字修饰局部变量
- 基本类型,是值不能被改变
- 引用类型,是地址值不能被改变,对象中的属性可以改变
- final修饰变量的初始化时机
- 类成员变量没有显示初始化时,JVM会默认初始化
- 加了final修饰后JVM不再默认初始化
24、抽象类
- 概述
- 抽象就是看不懂的
- 抽象类的特点
- 抽象类和抽象方法必须用abstract关键字修饰
- abstract class 类名{}
- public abstract void eat();
- 抽象类不一定有抽象方法,有抽象方法的类一定是抽象类或接口
- 抽象类不能实例化,那么抽象类如何实例化呢?
- 按照多态的方式,由具体的子类实例化。其实这也是多态的一种,抽象类多态。
- 抽象类的子类
- 要么是抽象类
- 要么重写抽象类中所有抽象方法
- 抽象类和抽象方法必须用abstract关键字修饰
- 抽象类成员特点
- 成员变量:既可以是变量,也可以是常量。abstract不能修饰成员变量
- 构造方法:有。用于子类访问父类数据的初始化。
- 成员方法:既可以是抽象的,也可以是非抽象的。
- 抽象类的成员方法特性:
- 抽象方法:强制要求子类做的事情
- 非抽象方法:子类继承的事情,提高代码复用性
- 面试题
- 面试题1:一个抽象类如果没有抽象方法,可不可以定义为抽象类?如果可以,有什么意义?
- 可以。这么做目的是不让其他类创建本类对象,交给子类完成
- 面试题2:abstract不能和哪些关键字共存
- static、final、private
- static和abstract,被abstract修饰的方法没有方法体,static修饰的方法可以用类名.调用,但是类名.调用抽象方法是没有意义的。
- final和abstract,被abstract修饰的方法强制子类重写,被final修饰的方法不让子类重写,矛盾。
- private和abstract,abstract修饰方法目的是让子类强制重写,private修饰方法不让子类继承,矛盾。
- 面试题1:一个抽象类如果没有抽象方法,可不可以定义为抽象类?如果可以,有什么意义?
25、接口
- 概述
- 从狭义的角度讲就是指Java中的interface
- 从广义的角度讲对外提供规则的都是接口
- 特点
- 接口用关键字interface表示
- interface 接口名 {}
- 类实现接口用implements表示
- class 类名 implements 接口名 {}
- 接口不能实例化,那么接口如何实例化呢?
- 按照多态的方式来实例化
- 接口的子类
- 可以是抽象类。但意义不大
- 可以是具体类。要重写接口中所有抽象方法(推荐)
- 接口用关键字interface表示
- 接口成员特点
- 成员变量:只能是常亮,并且是静态公共的。
- 默认修饰符:public static final
- 构造方法:无
- 成员方法:只能是抽象方法
- 默认修饰符:public abstract
- 成员变量:只能是常亮,并且是静态公共的。
26、抽象类和接口的区别
- 成员区别
- 抽象类
- 成员变量:可以变量,也可以常量
- 构造方法:有。
- 成员方法:可以抽象,也可以非抽象
- 接口
- 成员变量:只能是常量
- 成员方法:只能是抽象
- 抽象类
- 关系区别
- 类与类:继承,单继承
- 类与接口:实现,单实现,多实现
- 接口与接口:继承,单继承,多继承
- 设计理念区别
- 抽象类:被继承体现的是“is a”关系。抽象类中定义的是该继承体系的共性功能。
- 接口:被实现体现的是“like a”关系。接口中定义的是该继承体系的扩展功能。
27、如何编译运行带包的类
- javac编译的时候带上-d即可
- javac -d . HelloWorld.java
- 通过java命令执行。
- java 包名.HellWord
28、四种权限修饰符
29、类及其组成所使用的常见修饰符
- 修饰符:
- 权限修饰符:private,默认的,protected,public
- 状态修饰符:static,final
- 抽象修饰符:abstract
类:
- 权限修饰符:默认修饰符,public
- 状态修饰符:final
抽象修饰符:abstract
用的最多的就是:public
成员变量:
- 权限修饰符:private,默认的,protected,public
状态修饰符:static,final
用的最多的就是:private
构造方法:
权限修饰符:private,默认的,protected,public
用的最多的就是:public
成员方法:
- 权限修饰符:private,默认的,protected,public
- 状态修饰符:static,final
抽象修饰符:abstract
用的最多的就是:public
除此以外的组合规则:
- 成员变量:public static final
- 成员方法:
- public static
- public abstract
- public final
30、内部类访问特点
- 内部类可以直接访问外部类的成员,包括私有。
- 外部类要访问内部类的成员,必须创建对象。
- 创建内部类对象格式:
- 外部类名.内部类名 对象名 = 外部类对象.内部类对象;
- 成员内部类被静态修饰后的访问方式:
- 外部类名.内部类名 对象名 = 外部类名.内部类对象;
实例
public class Test { public static void main(String[] args) { Outer.Inner oi = new Outer.Inner(); oi.method(); Outer.Inner2.print(); } } class Outer { static class Inner { public void method() { System.out.println("method"); } } static class Inner2 { public static void print() { System.out.println("print"); } } }
面试题
要求:使用已知的变量,在控制台输出30,20,10。 class Outer { public int num = 10; class Inner { public int num = 20; public void show() { int num = 30; System.out.println(?); //num System.out.println(??); //this.num System.out.println(???); //Outer.this.num } } } class InnerClassTest { public static void main(String[] args) { Outer.Inner oi = new Outer().new Inner(); oi.show(); } }
局部内部类:在方法中定义的内部类
public class Test { public static void main(String[] args) { Outer o = new Outer(); o.method(); } } class Outer { public void method() { final int num = 10; //jdk1.8后不用再加final class Inner { public void print() { System.out.println(num); } } Inner i = new Inner(); i.print(); } }
匿名内部类:内部类的简化写法
- 前提:存在一个类或者接口
- 这里的类可以是具体类也可以是抽象类。
- 格式:
-
new 类名或者接口名(){
重写方法;
} - 本质:是一个继承了该类或者实现了该接口的子类匿名对象。
实例
public class Test { public static void main(String[] args) { PersonDemo pd = new PersonDemo (); //如何调用PersonDemo中的method方法呢? pd.method(new Person() { public void show() { System.out.println("Hello World"); } }); } } //这里写抽象类,接口都行 abstract class Person { public abstract void show(); } class PersonDemo { public void method(Person p) { p.show(); } }
- 面试题
按照要求,补齐代码
interface Inter { void show(); }
class Outer { //补齐代码 }
class OuterDemo {
public static void main(String[] args) {
Outer.method().show();
}
}
要求在控制台输出”HelloWorld”public class Test { public static void main(String[] args) { Outer.method().show(); //连续两次调用方法,说明返回的是个对象 } } //按照要求,补齐代码 interface Inter { void show(); } class Outer { //补齐代码 public static Inter method() { return new Inter() { public void show() { System.out.println("Hello World"); } }; } } //要求在控制台输出”Hello World”
- 前提:存在一个类或者接口