面向过程单位:函数;面向对象单位:类
JAVA类及类的成员:属性,方法,构造器;代码块,内容类
面向对象的特征:封装,继承,多态
关键字使用:this,super,package,import,static,final,interface,abstract等
类和对象:类是对相同事物的抽象,对象是具体(实例)
面对对象设计三步骤
对象在(jvm)内存中的分配涉及的内存结构(不涉及的有程序计数器,本地方法栈)
栈:对象名,存放对象在内存中的地址
堆:对象实体,包括属性(new 产生的)
方法区:加载类的模板结构
局部变量和属性在内存分配位置不同:属性随着对象的创建,存在堆中;局部变量存在栈中
生命周期属性随对象,局部变量随相应方法栈帧
局部变量不可以用权限修饰符修饰,而属性可以(封装性)
属性都有默认初始化值,而局部变量没有默认初始化值,使用前需要显式赋值
java中方法不区分相互顺序
方法的重载:同一个类中,允许同名方法,但满足参数不同(与形参名,权限修饰符,返回值无关)
相同的方法:方法名相同,形参列表相同
*println的重载:除char[]外形参都是对象,char[]的形参就是char[];
可变形参(int... a):实际调用时实参个数0个-多个;多个形参时可变形参必须声明在列表最后
可以与同类下同方法民构成重载(特例:参数为同类型的数组参数)
方法的值传递机制(Java的传递机制)
方法内声明的局部变量/方法的参数传递
基本数据类型:传递的是值
引用数据类型:传递的是地址
import关键字:显式引入指定包下的类
权限修饰符修饰类或类的内部成员:private,缺省,protected,public;当这些成员被调用时,可体现可见性的大小(体现封装性,满足高内聚低耦合需求)
main方法用private修饰则不再作为程序的入口
构造器( 类名() ):搭配new关键字,创建类的对象,在创建对象的同时,给对象相应属性初始化(系统默认提供一个空参的构造器,构造器权限与类相同,构造器也可以重载)
匿名对象(new () xxx),且匿名对象只能调用一次
未用static修饰的属性是实例变量,每一个对象都有单独的属性
类中属性赋值方法:默认初始化,显式初始化,构造器初始化,对象.方法;对象.属性;
Javabean:公用的类,提供空参公共的构造器,有属性且提供get()与set();
this关键字
应用场景:set方法的形参与属性名重名,用于表明当前(正在创建-在构造器中)对象的属性
this可以调用的结构:成员变量与方法(未用static修饰的),构造器
this在类中调用其它构造器可以使用this(形参)调用其它构造器,且必须声明在首行,因此一个构造器中最多声明一个其它构造器
快速创建get,set方法-alt+insert
面向对象特征二:继承性
考虑角度:自上而下,自下而上
好处:减少冗余,利于扩展,多可表示为is-a关系,为多态提供前提,子类获取父类中声明的属性和方法(不继承构造器),但是由于封装性可能不能直接调用一些属性和方法,还可以具有自己特有的部分
Java中的类,没显式表明其父类,则默认父类java.lang.object
java中类支持多层继承(直接父类,间接父类),单继承性(子类只能有一个父类,此局限性可以通过类实现接口解决)
方法的重写:子类对从父类继承而来的方法进行覆盖(子类与父类中同名的属性不会覆盖,用关键字进行区分,this与super)
重写的规则:方法名与形参列表必须保持不变,子类重写的方法的权限修饰符权限不小于父类中的修饰符(子类不能重写父类中private的方法,因为子类不能访问父类的private方法),返回值类型,父类为void或基本数据类型,则子类保持一致;若为引用数据类型,则子类中需一致或为其子类(抛出异常类型也是这个规则)
重载:两同一不同;重写:继承之后,覆盖同名同参的方法
super关键字:在子类中调用被子类重写的父类中的方法,调用父类中同名的属性,亦可以调用父类中的构造器(super(形参列表),只能写在首行,且与this(形参列表)只能存在一个,若都未调用,则默认调用父类空参构造器super())
在通过子类构造器创造对象的时候,一定在调用子类构造器的过程中直接或间接的调用了父类的构造器(一个类中n个构造器,最多n-1个中使用this(),至少一个使用super())
父类子类属性重名,调用方法时涉及该名属性按就近一致原则,即父类方法得到父类中属性,子类方法(或重写的方法)得到子类中属性
面向对象特征三:多态性(子类方法的多态性,方法的重写,决定了抽象类和接口的出现)
前提:继承关系,方法重写
体现:声明父类类型,赋予子类对象(多用于方法传参)
应用:虚拟方法调用(编译时认为是父类方法,执行时是子类重写的方法;编译看左,运行看右,在运行时体现出多态性)因此多态性只适用于方法,不适用于属性(编译与运行都看声明类型)
优劣:减少冗余与方法重载(抽象具体子类,易于扩展,eg:equals());创建的子类对象,加载了子类特有的属性方法,但声明为父类,并不可以直接调用
弊端解决:多态的逆过程-向下转型(转型前用instanceof判断,避免转换异常,格式 a instanceof B,判断对象a是否是类B的实例)
默认的父类(根类)-object类:无属性,一个空参构造器,11个通用方法
重点(2):
了解(2)
static关键字:静态的,用于修饰属性,方法,代码块,内部类
成员变量,用static-静态变量,类变量(有类即有,可以直接被类调用,也可以被对象调用,多个对象共享),不用-实例变量(创建对象才有,每个对象1份,只有对象能调用)
静态方法内可以调用静态属性和静态方法,不可以调用非静态成员(非静态中可调用静态),也不能用this与super,成员前省略的是类名(静态方法不可被重写,不存在多态性,与对象无关)
单例设计模式-某个类只能存在一个对象实例
实现:类的构造器私有化,在类的内部创建当前类的实例(此属性声明为static),通过static的get()得到构建的实例
两种模式:饿汉式-立即加载当前唯一实例(内存中加载较早,使用更快,线程安全的,但占用内存时间较长);懒汉式-延迟加载,使用时才创建实例(节省内存,但线程不安全)
类的成员:代码块与内部类
代码块:用于初始化类或对象信息,只能用static修饰(静态代码块-随着类的加载而执行,类只加载一次,则其只执行一次,初始化类的信息;非静态代码块-随着对象的创建而执行,多次创建对象,多次执行,初始化对象的信息【执行在构造器之前,与显式初始化的次序决定执行顺序】),可以有多个(多个之间的执行顺序按照声明顺序),静态代码块内部只能调用静态结构,不能够调用非静态的
代码块应用:不同构造器内相同的部分可提取到代码块,静态属性的初始化复杂的情况
内部类:定义在类中的类-遵循高内聚,低耦合
应用:thread中的state-表示线程生命周期
分类:成员内部类-静态(new 外部类.内部类)非静态(外部类对象.new 内部类),与类有相同性质,权限修饰符还可以用private和protected;局部内部类-匿名非匿名(匿名类或对象)
内部类可以调用外部类的属性和方法:外部类.this.结构
类的加载:由父及子(构造器一致)
final关键字的使用:修饰类(则不可被继承),方法(不可被重写),变量(只能赋值一次,视作常量,对于成员变量-显式赋值,代码块赋值,构造器赋值;局部变量-赋值后,不可更改)
final与static结合修饰成员变量:全局常量
抽象类与抽象方法(包含抽象方法的类必须是抽象类):abstract修饰类,抽象类不能实例化但包含构造器(因为子类需要调用),抽象类可以没有抽象方法;抽象的方法只有声明没有方法体,其功能已确定只是不知如何具体实现,实现交由子类,子类只有重写所有抽象方法后才可实例化(此时该子类才不是抽象类)
abstract不能修饰属性,构造器,代码块等;abstract不能与私有方法(私有方法不可重写),静态方法,final修饰的方法(不能重写),final修饰的类(不能继承)
接口:本质是规范,关键字interface,体现关系式a能够b,属性必须使用public static final修饰,方法(jdk8前)-抽象方法,abstract public修饰,修饰均可省略,不可以声明构造器,代码块
接口与类是实现关系,类可以实现多个接口(弥补单继承局限性),方法未全部实现则为抽象类
接口与接口是继承关系,可以多继承
接口的多态性,声明接口,指向实现接口的类
创建匿名实现类的对象,用接口名创建对象临时重写抽象方法 new 接口(){重写};
抽象类与接口:共-都可以定义抽象方法,都不能实例化,异-抽象类有构造器,接口无构造器
jdk8接口新特性:静态方法-只能通过接口调用,不能通过实现类调用;默认方法-实现类可以继承且重写,实现类实现多个接口中存在同名同参默认方法,则必须对其重写;类优先原则-子类继承父类且实现了接口,同名同参方法未重写,则调用的是父类中的;在子类中调用接口中的默认方法-接口名.super.方法名
jdk9-接口中可以定义私有方法
涉及的匿名声明方法(内部类):
public class OuterClassTest2 {
public static void main(String[] args) {
SubA a = new SubA();
a.method();
//举例1:提供接口匿名实现类的对象
A a1 = new A(){
public void method(){
System.out.println("匿名实现类重写的方法method()");
}
};
a1.method();
//举例2:提供接口匿名实现类的匿名对象
new A(){
public void method(){
System.out.println("匿名实现类重写的方法method()");
}
}.method();
//举例3:
SubB s1 = new SubB();
s1.method1();
//举例4:提供了继承于抽象类的匿名子类的对象
B b = new B(){
public void method1(){
System.out.println("继承于抽象类的子类调用的方法");
}
};
b.method1();
System.out.println(b.getClass());
System.out.println(b.getClass().getSuperclass());
//举例5:
new B(){
public void method1(){
System.out.println("继承于抽象类的子类调用的方法1");
}
}.method1();
//举例6:
C c = new C();
c.method2();
//举例7:提供了一个继承于C的匿名子类的对象
C c1 = new C(){};
c1.method2();
System.out.println(c1.getClass());
System.out.println(c1.getClass().getSuperclass());
C c2 = new C(){
public void method2(){
System.out.println("SubC");
}
};
c2.method2();
}
}
interface A{
public void method();
}
class SubA implements A{
@Override
public void method() {
System.out.println("SubA");
}
}
abstract class B{
public abstract void method1();
}
class SubB extends B{
@Override
public void method1() {
System.out.println("SubB");
}
}
class C{
public void method2(){
System.out.println("C");
}
}
枚举类(enum):类的对象有限且确定,若实例只有一个可以用单例模式实现
定义方式:私有化类的构造器;类内部创建对象,public static final修饰(jdk5前,class定义)
对象省去修饰词,放在类开头,对象间用逗号隔开(jdk5,,enum定义,继承父类Enum)
枚举类实现接口:类中重写方法,每个对象调用方法一致;在创造对象时重写方法,各不相同
常用方法:
注解:@注解名
常用注解:@override-重写;@deprecated-过时,可以用;@suppresswarning-抑制编译警告
元注解:对现有的注解进行解释说明的注解。
(1)@Target:用于描述注解的使用范围
可以通过枚举类型ElementType的10个常量对象来指定
TYPE,METHOD,CONSTRUCTOR,PACKAGE.....
(2)@Retention:用于描述注解的生命周期
可以通过枚举类型RetentionPolicy的3个常量对象来指定
SOURCE(源代码)、CLASS(字节码)、RUNTIME(运行时)
唯有RUNTIME阶段才能被反射读取到。
(3)@Documented:表明这个注解应该被 javadoc工具记录。
(4)@Inherited:允许子类继承父类中的注解
Junit单元测试-白盒测试
单元测试方法,需要满足:- 所在的类必须是public的,非抽象的,包含唯一的无参构造器。
- @Test标记的方法本身必须是public,非抽象的,非静态的,void无返回值,()无参数的。
包装类:使基本数据类型具有引用数据类型的相关特征
基本数据类型与包装类之间转换:前-后:使用包装类的构造器;包装类的valueof();
自动装箱-直接赋值(jdk5新特性);
后-前:包装类的xxxvalue();自动拆箱-直接赋值(jdk5)
string与基本数据类型,包装类的转换:
前-后:调用相应包装类.paresXxx(xxx);
后-前:调用string的静态方法valueof(xxx);+“”连接运算;
参考试题:
//说明:如果赋值的值在[-128,+127]范围内,
//则Integer对象使用的是IntegerCache中数组cache中的元素
public class InterviewTest1 {
public static void main(String[] args) {
Integer i = new Integer(1);
Integer j = new Integer(1);
System.out.println(i == j);//false
//底层都会调用Integer的valueOf()
Integer m = 1; //自动的装箱
Integer n = 1;
System.out.println(m == n);//true
Integer x = 128;
Integer y = 128;
System.out.println(x == y);//false
}
}
面向对象的理解:(核心)-类与对象,三大特征;接口