面向对象
1 使用继承来实现复用时,子类对象可以直接赋给父类变量,这个变量具有多态性。
2 构造器用于对类实例经行初始化操作,构造器支持重载,如果多个重载构造器里包含相同初始化代码,可以把他们放在普通初始化块中完成,初始化块总在构造器执行前被调用。还提供静态初始化块,用于对初始化类,在类初始化阶段被执行。
3 类被认为是自定义的数据类型,使用类定义变量。称为引用类型变量,所有类是引用数据类型。
4 Java提供private protected public 三个访问控制修饰符来实现良好封装。
5 static 修饰的静态成员不能访问没有static修饰的非静态成员。
6 field 用于定义类或类实例包含的状态数据,方法用于定义类或类实例的行为特征或功能实现,构造器用于构造类的实例。
7 field定义 【修饰符】 field类型 field名【=默认值】 修饰符可以省略,可以是public protected private static final, public protected private只能出现一个,可以和static final组合修饰field
8 method定义 【修饰符】修饰符可以省略,可以是public protected private static final, abstract, public protected private只能出现一个,final, abstract只能出现一个,可以和static 组合修饰method
9 构造器不能定义返回值类型,也不能使用void定义构造器没有返回值,否则编译时不会出错,把他当方法处理。构造器有隐式的返回值类型,就是当前类
10 Person p = new Person() 产生了p变量,和Person对象
11 对象this引用 , 总是指向调用该方法的对象,在构造器中引用正在初始化 的对象,在方法中引用调用该方法的对象。作用是让一个类的方法访问该类的另一个方法或field。如果没有对象,则不能访问类中的其他方法。大部分时,普通方法访问其他方法,field时无需使用this前缀,但如果方法中某个变量和field同名,但又要访问这个field变量,则用this前缀
class Person { int age; String name; void jump() { } void run() { age = 10; this.age = 10; new Person().age = 10; jump(); this.jump(); new Person().jump(); } public static void main(String[] args) { run() // 错 age = 10 // 错 } }
class Person { int age; String name; void jump() { } void run() { int age = 10; this.age = 10; // 用this } }
12 方法不能独立定义,只能在类体里定义,方法要么属于类本身(static), 要么属于类的对象。永远不能独立执行方法,必须使用类或对象做调用者。使用不同对象作为调用者调用一个普同方法,可能得到不同结果。
13 方法参数传递机制 :如果方法中包括形参的声明,调用方法时必须给形参指定参数值,调用方法时实际传给形参的参数值被称为实参,实参如何传入方法呢?值传递,将实际参数值的副本传入方法内,参数本身不会受影响。基本类型和引用类型都是值传递,
static void swap(int a, int b) { int temp = b; b = a; a = b; } public static void main(String[] args) { int a = 9; int b = 10; System.out.println("a = " + a + " b = " + b); swap(a, b); System.out.println("a = " + a + " b = " + b); }
长度可变的形参只能处于形参列表的最后,方法中只能包含一个长度可变形参,长度可变形参可以传入多个参数,也可以传入一个数组。
static void swap(String a, int... b) { for (int i : b) { System.out.println(i); } } public static void main(String[] args) { swap("a", 1,2,3); swap("a", new int[]{1,2,3}); }
14 方法重载
同一个类里定义多个同名方法,只要形参列表不同就行,确定一个方法要3个要素1 调用者(方法的所属者,类,对象),方法名,形参列表。
方法重载要求两同一不同,同一个类中方法名相同,参数列表不同,和返回值,修饰符没关系。
可变参数方法重载,
public class My { static void swap(int... b) { System.out.println("参数可变"); } static void swap(int b) { System.out.println(b); } public static void main(String[] args) { swap(1,2,3); // 执行1 swap(new int[]{3}); // 执行1 swap(); // 执行1 swap(1); // 执行2 } }
成员变量:在类范围内定义 的变量,类成员变量从类的准备阶段开始存在,直到系统完全销毁这个类,类成员变量的作用域和类的生存范围相同,实例成员变量从实例被创建起开始存在,直到系统完全销毁实例。
局部变量有3种 1 形参,方法签名时定义的变量,方法内有效,2 方法局部变量:方法体内定义的变量,从变量定义的地方开始到方法结束有效,3代码块局部变量:从变量定义的地方开始到块结束有效,除形参外,必须为局部变量赋值才可以使用她。
一个类中不允许定义两个名字相同的局部变量或成员变量,但允许局部变量和成员变量同名,如果方法里的局部变量和成员变量同名,局部变量会覆盖成员变量,如果想使用成员变量可以使用this或类名
public class My { static int a = 0; int b = 0; { int b = 9; System.out.println(this.b); } static void swap(int... b) { int a = 9; System.out.println(My.a); } static void swap(int b) { System.out.println(b); } public static void main(String[] args) { new My(); } }
在类的准备阶段,系统将会为类的类成员变量分配内存空间,并指定默认初始值。只存在一份。
在创建对象时,系统会为实例成员变量分配内存空间,并指定默认初始值。
15 外部类可以使用public和包访问权限,private 和protected对外部类没有意义。
16 模块设计追求高内聚(尽可能把模块的内部数据,功能实现细节隐藏在模块内部独立完成,不允许外部直接干预)低耦合(仅暴露少量方法给外部使用)
17 Java引入包机制,提供类的多层命名空间,用于解决类的命名冲突,类文件管理问题。位于包中的每个类的完整类名应该是包名和类名的组合。需要2方面保证1 源文件使用package指定包名,2 class文件必须放在对应路径下。
inport 包名,类名(*) 导入静态方法或域 inport static 包名.类名.属性|方法(*)
18 方法重写 “两同两小一大” , 两同:方法名,参数列表相同,两小:子类方法返回值类型比父类更小或相等,声明抛出的异常比父类声明抛出异常更小或相等。一大:子类方法访问权限比父类更大或相等。覆盖和被覆盖方法要么都是类方法,要么都是实例方法。
class BaseClass { public static void test() { } } class SubClass extends BaseClass{ public void test() { // 错误 一个类方法,一个实例方法 } }
当子类覆盖父类方法后,子类对象无法访问父类中被覆盖方法,但可以在子类方法中调用父类中被覆盖方法(可是使用super实例方法,或父类类名,类方法,作为调用者调用父类中被覆盖方法)
如果父类方法private,该方法对子类隐藏,子类无法方法该方法,也无法重写该方法,如果子类中定义了一个与父类private方法具有相同方法名,形参列表,返回值类型方法,仍不是重写,只是子类中的一个新方法。
class BaseClass { private static void test() { } } class SubClass extends BaseClass{ public void test() { // 不是重写,不加static } }
19 可以使用super调用从父类继承的方法或field。如果子类定义了和父类同名的field,则会发生子类field隐藏父类field的情况,可以使用super访问隐藏field
class BaseClass { public void a() { } } class SubClass extends BaseClass{ public void test() { // 不是重写,不加static super.a(); } }
如果子类中没有包含和父类同名field,子类实例方法中访问该field时,无需显示使用super或父类名作为调用者,如果在某个方法中访问名为a的field,但没有显示指定调用者,则查找a的顺序为 1 局部变量 2 当前类field 3 父类field 访问哪个实例变量由声明变量类型决定
public class My { public static void main(String[] args) { SubClass sb = new SubClass(); System.out.println(sb.a); // 错 System.out.println(((BaseClass)sb).a); } } class BaseClass { public int a = 0; } class SubClass extends BaseClass{ private int a = 9; }
20 Java引用变量有两个类型,一个是编译类型,一个是运行时类型。编译时类型由声明该变量时用的类型决定,运行时类型由实际赋给该变量的对象决定,如果编译类型和运行类型不一致,可能发生多态。
21 向上转型:把子类对象赋给父类引用变量,无需任何类型转换。
22 多态:相同类型的变量,调用同一个方法时呈现出多种不同行为特征。
23 引用变量强制类型转换:引用变量只能调用他编译时类型的方法,bu能调用它运行时类型方法,如果需要让变量调用运行时类型方法,需要把变量强制类型转换为运行时类型,引用类型之间的转换只能在具有继承关系的两个类型之间经行,否则就会编译错误。
public class My { public static void main(String[] args) { SubClass sb = new SubClass(); Math m = (Math)sb; // 无法转换,没有继承关系,编译出错 } } class BaseClass { } class SubClass extends BaseClass{ private int a = 9; }
public class My { public static void main(String[] args) { Object sb = new SubClass(); Math m = (Math)sb; // 将抛出classcastexceptio } } class BaseClass { } class SubClass extends BaseClass{ private int a = 9; }
24 instanceof 运算符前一个操作数是一个引用类型变量,后一个操作数是一个类,判断前面的对象是否是后面的类或子类的实例。前面操作数的编译时类型要么与后面的类相同,要么具有继承关系,否则会编译错。
public boolean equals(Object anObject) { if (this == anObject) { return true; } if (anObject instanceof String) { String anotherString = (String) anObject; int n = value.length; if (n == anotherString.value.length) { char v1[] = value; char v2[] = anotherString.value; int i = 0; while (n-- != 0) { if (v1[i] != v2[i]) return false; i++; } return true; } } return false; }
25 初始化块,声明实例field指定的默认值都可以认为是对象的初始化块,他们的执行顺序与源程序的排列顺序相同
public class My { public static void main(String[] args) { System.out.println(new SubClass().a); // 输出9 } } class SubClass{ { a = 0; } int a = 9; }
26 超类静态初始化块 , 父类静态初始化块,子类静态初始化块 超类初始化块,构造器。。。。
class Root { static { System.out.println("root static"); } { System.out.println("root not static"); } Root() { System.out.println("root construct"); } } class Mid extends Root { static { System.out.println("Mid static"); } { System.out.println("Mid not static"); } Mid() { super(); System.out.println("Mid construct"); } } class Leaf extends Mid { static { System.out.println("Leaf static"); } { System.out.println("Leaf not static"); } Leaf() { super(); // 默认调用 System.out.println("Leaf construct"); } } root static Mid static Leaf static root not static root construct Mid not static Mid construct Leaf not static Leaf construct