2、编程思想:
OOP 面向对象编程
面向对象(核心思想):
1、封装:信息的隐藏
2、继承:并不是所有东西都可以继承,继承过来的可以直接用,有的也不能直接用
3、多肽:相同类型的不同对象,在执行相同操作时,表现出来的形式不同
2.1:封装
定义方法:
modifiers(修饰符) return_type name ([argumengt list])[throws Exception]{
//block
}
modifiers:修饰符
1、 访问修饰符:public protected default private
2、 其他修饰符:final static abstract
a) 访问修饰符必须有
b) 其他修饰符根据需要添加
return_type:返回值类型
1、 void:返回空(没有返回值)
调用方法时,不能用任何变量接受
2、 任意数据类型:返回返回值类型的数据
调用方法时,可以用返回值类型的变量接收方法的返回值
methodName:方法名
1、 遵从标识符的命名规则
2、 第一个单词首字母小写,后面的大写
[argumengt list]:参数列表(可有可无)
数据类型 变量名1,数据类型 变量名2,……
[throws Exception]:抛出异常
方法调用:
对象.方法名(【实参】)
参数传递:
基本数据类型 传值
引用数据类型 传引用(地址)
2.2:继承
代码的复用: is a
class A{ }
class B extends A{
}
单继承:extends 后面只能跟一个类
属性、方法、构造器
属性、方法可以继承
能不能继承和能不能访问是两回事
构造器不能被继承:
1、 子类的构造器会隐含的调用父类无参的构造器
2、 如果父类没有无参数的构造器,那么子类的构造要显式的调用父类带参数的构造器,用super 可以调用有参的和无参的
3、 当在子类中显式调用父类的构造器时,必须是子类构造器的第一行代码:super();
2.3:多态
1、 发生在子父类之间,重写的方法上;
2、 父类的引用指向子类的对象
3、 父类的引用调用方法时:
编译阶段:看=左边声明的类中是否有调用的方法,如果有,编译通过;如果没有,但是=左边声明的类的父类中有调用的方法,编译也可以通过;
运行阶段,看=右边真正创建的对象中是否有调用的方法,如果有,直接调用;如果没有调用声明的类中的方法
2.4:方法重载
方法的重载(method Overloading):
1、 在同一个类中,方法名相同的方法
2、 重载的方法参数列表不同(参数列表不同包括个数不同或类型不同或顺序不同)
3、 返回值类型可以不同
2.5:方法重写
方法重写Overriding
super.setAge(18); super调用父类的方法
1、 发生在子父类之间(在子类中重写父类的方法)
2、 方法名、参数列表、“返回值类值“相同
3、 访问不能被缩小
4、 异常不能被扩大
2.6:Constructor
Constructor:(构造器、构造函数、构造方法)
语法:
访问修饰符 ClassName(【args list】){ }
1、 如果一个类中,程序员没有在这个类中定义任何的构造器,jvm会给这个类提供一 个默认的无参的空的构造器; public ClassName(){ }
2、 如果程序员在一个类中定义了任意一个构造器,那么这个jvm提供的默认的无参的 空的构造器就不存在了;
3、 如果在类中定义多个构造器,那么这多个构造器就叫构造器重载,主要是构造器的参数列表不同(个数不同或类型不同或顺序不同)
4、 建议如果在类中定义了带参数的构造器,那么要把无参数的构造器也定义一下
5、 构造器与构造器之间可以相互调用
2.7:this
this:当前对象
1、 区分实例变量和局部变量 this.xx=xx
2、 调用当前对象中的方法 this.methedName();
3、 在一个类中的一个构造器调用另一个构造器;调用时,this(args list)语句必须放在第一行
2.8:super
super:
1、 在子类中调用父类的属性和方法名
2、 在子类的构造器中显式的调用父类的构造器
2.9:创建对象实例
创建对象()实例:
1、 分配内存
2、 对实例变量进行默认初始化
3、 可以进行显式初始化
4、 调用构造器
5、 返回对象的引用
2.10:Static
static 是一个关键字也是一个修饰符;
修饰属性 :
静态和非静态区别:
1、static 修饰的静态变量存储在静态存储区,实例变量(普通变量)存储在堆中
2、静态变量与类相关,普通变量则与实例相关
3、静态变量可以使用类名直接调用;实例变量使用对象,进行调用的(方法)
4、静态变量加载时间:随类的加载,而加载到内存;实例对象加载时间:创建对象时 加载到内容
1、 修饰属性
语法:
class ClassName{
static dataType variableName;
}
调用:
className. variableName;
2、 理解:
1)static 修饰的属性什么时候存在? 在类加载时或者第一次使用这个类 时;jvm会对static修饰的变量分配内存、默认初始化、显示初始化
2)static 修饰的变量是依赖类的,和通过创建的对象没有关系
3)static 修饰的变量是全局变量,多个对象共享static修饰的变量
ClassName c=new ClassName();
1)类加载
i:对静态变量进行分配内存、默认初始化、显示初始化
ii:对实例变量分配内存、默认初始化、显示初始化、调用构造器、 返回引用
2)修饰方法
public static returnTypename(){
}
3、 调用:
ClassName.name([……]);
1) static修饰的方法也是依赖于类的
2) static 修饰的方法不能使用非静态的属性和方法
3) Static 修饰的方法不能被重写成非静态
4、 顺序问题:
引用对象时类加载已结束
类加载时,引用对象还未开始
static 修饰匿名块,静态块
匿名块:
语法:
class ClassName{
//匿名块
{
}
}
调用:
1、创建匿名块所在的对象时,匿名块就会被调用;
2、创建对象时:对实例变量进行分配内存、默认初始化、显示初始化、调用匿名 块(如果有多个匿名块,按匿名块定义的顺序调用、调用构造器、返回引用)
静态块:
语法:
class ClassName{
//静态块
static{
}
}
调用:
类加载或第一次使用类时;jvm会对静态变量进行分配内存、默认初始化、显示初 始化、调用静态块
Math.random(); //静态方法,不需要new对象
System.arraycopy();
静态导入 import static com.briup.ch09.Student
import static java.lang Math.*
2.11:final
final:最终的;即使关键字又是修饰符
1、final可以用来修饰类,但不可以被继承;
2、final可以修饰方法,但是final修饰的方法不能被重写
3、final可以修饰属性,final修饰的属性只能被赋一次值;可以在显示初始化、匿名块、 构造器的任何位置给final修饰的属性赋一次值。
4、可以修饰局部变量;final修饰的局部变量只能赋一次值
class Test{
//static final同时修饰的值是不能改变的 称为常量(所有字母都大写)
static final int COUNT=10;
static{
}
static final void test(){
}
}
2.12:abstract
abstract 修饰符(可以当作关键字来看,站在面向对象角度来用):
1、 类和方法
a) abstract class ClassName{ },
b) 抽象类是不能创建实例的;(不能直接创建抽象类的对象)
c) 抽象类中可以定义普通类中定义的所有内容
d) abstract 修饰的方法,是抽象方法,抽象方法没有方法体;
abstract return Typename
e) 有抽象方法的类,一定是抽象类;
f) 抽象类中,可以有抽象方法,可以没有
g) 抽象类就是为了被继承:子类继承抽象类的时候子类也可以是抽象类,也可以是普通类,如果子类是抽象类,这个子类中可以重写父类的抽象方法,也可以不重写;如果子类是普通,那么在子类中必须重写父类的抽象方法(实现父类的抽象方法)
2.13:接口interface
接口:interface(可看作抽象的抽象)
implements 实现
接口:
语法:
定义: interface interfaceName{
//常量
//抽象方法
}
//子类实现特殊的父类
public class Fish implements Food{
//重写接口抽象方法//实现接口的抽象方法
}
不能直接创建接口本身的对象
接口的引用指向显示类的对象
interfaceName c=new ClassName();
面向接口编程:
可扩展性;
2.14:内部类
类里面定义的类,就是内部类;
2.14.1:静态内部类:
1、 在类中直接定义静态内部类
class Oute{
static class Inner{
}
}r
2、 静态内部类中可以定义类中能定义的所有内容
3、 静态内部类中可以直接使用外部类的静态内容
4、 静态内部类所在的外部类中可以使用静态内部类的内容;静态的直接通过静态内部类。静态属性或方法;非静态的需要创建静态内部类的对象去调用
5、 在外部类的外面使用静态内部类的内容;
静态的:
Outer.Inner.静态属性 | 方法
非静态的:
创建静态内部类的对象去调用
new Outer.Inner();
2.14.2:成员内部类:(相当于类中的一个成员变量)
成员内部类中不能有static的声明属性或者方法
成员内部类可以由public protected default private修饰
成员内部类是依赖于外部类的对象而存在的
外部类.内部类 var = new 外部类().内部类();
1) 在创建实例内部类的实例时,外部类的实例必须已经存在。
Outer.InnerTool tool = new Outer().new InnerTool();
等价于:
Outer outer = new Outer();
Outer.InnerTool tool = outer.new InnerTool();
以下代码会导致编译错误:
Outer.InnerTool tool = new Outer.InnerTool();
2) 实例内部类的实例自动持有外部类的实例的引用。在内部类中, 可以直接访问外部类的所有成员,包括
成员变量和成员方法。
public class A {
private int a1;
public int a1;
static int a1;
public A(int a1, int a2) {
this.a1 = a1;
this.a2 = a2;
}
protected int methodA() {
return a1*a2;
}
class B {
int b1 = a1; //直接访问private的a1
int b2 = a2; //直接访问public的a2
int b3 = a3; //直接访问static的a3
int b4 = A.this.a1; //访问类A的当前实例中的a1
int b5 = methodA(); //访问methodA()方法
}
public static void main(String args[]) {
A.B b = new A(1,2).new B();
System.out.println("b.b1="+b.b1); //打印b.b1=1;
System.out.println("b.b2="+b.b2); //打印b.b2=2;
System.out.println("b.b3="+b.b3); //打印b.b3=0;
System.out.println("b.b4="+b.b4); //打印b.b4=3;
System.out.println("b.b5="+b.b5); //打印b.b5=2;
}
}
3) 外部类实例与内部类实例之间是一对多的关系,一个内部类实例只会引用一个外部类实例,而一个外部类实例对应零个或多个内部类实例。在外部类中不能直接访问内部类的成员,必须通过内部类的实例去访问。
class A {
class B {
private int b1 = 1;
public int b2 = 2;
class C{}
}
public void test() {
int v1 = b1; //invalid
int v2 = b2; //invalid
B.C c1 = new C(); //invalid
B b = new B(); //valid
int v3 = b.b1; //valid
int v4 = b.b2; //valid
B.C c2 = b.new C(); //valid
B.C c3 = new B().new C(); //valid
}
}
4) 实例内部类中不能定义静态成员,而只能定义实例成员。
5) 如果实例内部类B与外部类A包含同名的成员,那么在类B中, this.v 表示类B的成员, A.this.v表示类A的成员。
2.14.3:局部内部类:(相当于一个方法中的局部变量)
局部内部类不能用public private等修饰符修饰
写在方法当中,而且只能在方法当中使用
可以访问外层类的普通成员变量和静态成员变量以及普通方法和静态方法,也可以 访问该内部类所在方法当中的局部变量,但是这个局部变量必须是final修饰;
1) 局部内部类只能在当前方法中使用。
class A {
B b = new B(); //编译错误;
public void method() {
class B{
int v1;
int v2;
class C {
int v3;
}
}
B b = new B(); //合法
B.C c = b.new C(); //合法
}
}
2) 局部内部类和实例内部类一样,不能包含静态成员。
class A {
public void method() {
class B{
static int v1; //编译错误
int v2; //合法
static class C { //编译错误
int v3;
}
}
}
}
3) 在局部内部类中定义的内部类也不能被public、protected和private这些访问控制修饰符修饰;
4) 局部内部类和实例内部类一样,可以访问外部类的所有成员,此外,局部内部类还可以访问所在方法中的final类型
的参数和变量。
2.14.4:匿名内部类:(和局部内部类很相似)
匿名内部类也是用的最多的内部类
可以写成成员变量的形式,也可以写在方法当中,一般写在方法当中较多
匿名内部类里可以访问外部类的普通属性和方法,已经静态属性和方法,如果要访问 这个内部类所在方法中的局部变量,那么要求这个局部变量必须是final修饰的
匿名内部类里面没有构造函数,因为这个类没有名字,所以在其他地方不能用
public class Hello{
public void test(){
//假如A是同包下的一个接口,有一个抽象方法go
A a = new A(){
public void go(){
System.out.println("gogogo");
}
};
}
}
2.15:== ; equals
== ;equals
1、 一般情况下;== 和 equals 比较的地址值;(只要是创建新的对象,地址值都是不同的)
2、 如果自己的类重写了equals方法;比较的还是地址值;equals 比较的什么要看你怎么重写的equals
3、 在字符串和包装器中,如果直接赋值;那么直接赋值的内容如果相同; 比较时一般为true;是因为它们有缓冲区;
Integer i=10;
Integer i1=10;
ii1; //true
Integer i=128; //超出了缓存区的范围(-128——127)
Integer i1=128;
ii1; //false