Java 类&对象
Java 类&对象
初识类和对象
1、类:现实生活中的某种事物的统称;
2、对象:现实生活中的某种事物的实体;
例:车(类)
对象:
宝马
奔驰
法拉利
......等等
面向对象和面向过程比较
1、面向过程:强调的是功能行为,以函数为最小单位,考虑怎么做。
2、面向对象:强调具备了功能的对象,以类/对象为最小单位,考虑谁来做。
面向对象的两个重要概念
1、类:对一类事物的描述,是抽象的、概念上的定义。
2、对象:是实际存在的该类事物的每个个体,因而也称为实例(instance)。
- 面向对象程序设计的重点是类的设计
- 设计类,就是设计类的成员(field)
例:把大象装进冰箱
面向过程:打开冰箱门->抬起大象放入冰箱->关闭冰箱门
面向对象:分析问题,获取类对象->人、大象、冰箱
类
人{
打开(冰箱){
冰箱.开开();
}
装(大象){
大象.进入();
}
关闭(冰箱){
冰箱.闭合();
}
}
类
冰箱{
开开(){
}
闭合(){
}
}
类
大象{
进入(){
}
}
类的实例比(创建对象)
1、说明:对象,是由类new出来的,创建出来的。
2、例:房子设计图(类)-> 房子(对象)
3、典型代码:
Person p1 = new Person();
Person p2 = new Person();
Person p3 = p1;//没有新创建一个对象,共用一个堆空间中的对象实体。
类成员
1、属性(field)
-
类成员变量
1.1 直接定义在类的一对{}内
1.2 可以在声明属性时,指明其权限,使用权限修饰符。
1.3 封装性:常用的权限修饰符:private、缺省、protected、public
1.4 类的属性,根据其类型,都默认初始化值。
整型(byte、short、int、long:0)
浮点型(float、double:0.0)
字符型(char:0 (或'\u0000'))
布尔型(boolean:false)
引用数据类型(类、数组、接口:null)1.5 加载到堆空间中(非static)
-
局部变量
2.1 局部变量:声明在方法内、方法形参、代码块内、构造器形参、构造器内部的变量。
2.2 不可以使用权限修饰符。
2.3 没默认初始化值。意味着,我们在调用局部变量之前,一定要显式赋值。特别地:形参在调用时,我们赋值即可。
2.4 加载到栈空间
2、方法(method)
方法的声明:权限修饰符 返回值类型 方法名(形参列表){
方法体
}
注意:static、final、abstract 来修饰的方法,后面再讲。
- return关键字
1.1 使用范围:使用在方法体中
1.2 作用:
? 1.2.1 结束方法
? 1.2.2 针对于返回值类型的方法,使用"return 数据"方法返回所要的数据
1.3 注意点:return关键字后面不可以声明执行语句。
-
方法的重载
2.1 方法重载的概念
定义:在同一个类中,允许存在一个以上的同名方法,只要它们的参数个数或者参数类型不同即可。
总结:"两同一不同":同一个类、相同方法名参数列表不同,参数个数不同,参数类型不同;
- 可变个数形参的方法
public void show(String ... strs){
for(int i = 0;i < strs.length;i++){
System.out.println(strs[i]);
}
}
-
java值传递机制
4.1 传递规则
? 如果变量是基本数据类型,此时赋值的是变量所保存的数据值(字面量的值)。
? 如果变量是引用数据类型,此时赋值的是变量所保存的数据的地址值。
4.2 针对于方法的参数概念
? 形参:方法定义时,声明的小括号内的参数
? 实参:方法调用时,实际传递给形参的数据
3、构造器(construct)
-
构造器的作用
1.1 创建对象
1.2 初始化对象的信息
-
如果没显式的定义类的构造器的话,则系统默认提供一个空参的构造器
-
定义构造器的格式:权限修饰符 类名(形参列表){}
-
一个类中定义的多个构造器,彼此构成重载
-
一旦我们显式的定义了类的构造器之后,系统就不再提供默认的空参构造器
-
一个类中,至少会有一个构造器。
4、补充:属性的赋值顺序
- 默认初始化
- 显式初始化
- 构造器中初始化
- 通过"对象.方法" 或 "对象.属性"的方式,赋值
关键字 1: this package/import
1、this理解为:当前对象 或 当前正在创建的对象
2、为了更好的实现项目中类的管理,提供包的概念
-
1 使用package声明类或接口所属的包,声明在源文件的首行
-
2 包,属于标识符,遵循标识符的命名规则、规范(xxxyyyzzz)、“见名知意”
-
3 每"."一次,就代表一层文件目录。
3、import:导入包
-
1 在源文件中显式的使用import结构导入指定包下的类、接口
-
2 声明在包的声明和类的声明之间
-
3 如果需要导入多个结构,则并列写出即可
-
4 可以使用"xxx.*"的方式,表示可以导入xxx包下的所结构
-
5 如果使用的类或接口是java.lang包下定义的,则可以省略import结构
-
6 如果使用的类或接口是本包下定义的,则可以省略import结构
-
7 如果在源文件中,使用了不同包下的同名的类,则必须至少一个类需要以全类名的方式显示。
-
8 使用"xxx.*"方式表明可以调用xxx包下的所结构。但是如果使用的是xxx子包下的结构,则仍需要显式导入
-
9 import static:导入指定类或接口中的静态结构:属性或方法。
面向对象三大特性:封装 继承 多态
1、访问控制权限修饰符 private 缺省 protected public
- 权限从小到大顺序为:private < 缺省 < protected < public
- 修饰类的话,只能使用:缺省、public
2、派生类 extends(提高代码的复用性)
-
继承性的格式:
class A extends B{}
A:子类、派生类、subclass
B:父类、超类、基类、superclass
-
类继承父类以后有哪些不同?
- 1 体现:一旦子类A继承父类B以后,子类A中就获取了父类B中声明的所有的属性和方法。
特别的,父类中声明为private的属性或方法,子类继承父类以后,仍然认为获取了父类中私的结构。只因为封装性的影响,使得子类不能直接调用父类的结构而已。
- 2 子类继承父类以后,还可以声明自己特有的属性或方法:实现功能的拓展。子类和父类的关系,不同于子集和集合的关系。
-
Java中继承性的说明
-
1 一个类可以被多个子类继承。
-
2 Java中类的单继承性:一个类只能有一个父类
-
3 子类直接继承的父类,称为:直接父类。间接继承的父类称为:间接父类
-
4 子类继承父类以后,就获取了直接父类以及所间接父类中声明的属性和方法
-
-
java.lang.Object类的理解
-
1 如果我们没显式的声明一个类的父类的话,则此类继承于java.lang.Object类
-
2 所有java类(除java.lang.Object类之外都直接或间接的继承于java.lang.Object类,所的java类具有java.lang.Object类声明的功能
-
-
方法的重写(运行后绑定)
- 1 什么是方法的重写(override 或 overwrite)?
? 子类继承父类以后,可以对父类中同名同参数的方法,进行覆盖操作。
-
super关键字
-
1 通过使用"super.属性"或"super.方法"的方式,显式的调用父类中声明的属性或方法;
-
2 特殊情况:当子类和父类中定义了同名的属性时,我们要想在子类中调用父类中声明的属性,则必须显式的使用"super.属性"的方式,表明调用的是父类中声明的属性;
-
3 特殊情况:当子类重写了父类中的方法以后,我们想在子类的方法中调用父类中被重写的方法时,则必须显式的使用"super.方法"的方式,表明调用的是父类中被重写的方法。
-
-
子类对象实例化过程
this(...) 或 super(...) 或 super()
3、一种事物的多种形态,抽象概念(多态)
-
何为多态性?
对象的多态性:父类的引用指向子类的对象(或子类的对象赋给父类的引用)
举例:
Person p = new Man();Object obj = new Date(); -
多态性的使用:虚拟方法调用
- 1 有了对象的多态性以后,我们在编译期,只能调用父类中声明的方法,但在运行期,我们实际执行的是子类重写父类的方法。
总结: 编译,看左边;运行,看右边。
-
多态性使用的注意点
对象的多态性,只适用于方法,不适用于属性(编译和运行都看左边)
-
关于向上转型与向下转型(instanceof)
-
1 a instanceof A : 判断对象 a 是否是类A的实例。如果是,返回true;如果不是,返回false。
-
2 如果 a instanceof A 返回true,则 a instanceof B 也返回true. 其中,类B是类A的父类。
-
4、Object类的使用
-
java.lang.Object类的说明
-
1 Object类是所有Java类的根父类
-
2 如果在类的声明中未使用extends关键字指明其父类,则默认父类为java.lang.Object类
-
3 Object类中的功能(属性、方法)具有通用性。
属性:无
方法:equals()/toString()/getClass()/hashCode()/clone()/finalize()/wait()/notify()/notifyAll()
-
4 Object类只声明了一个空参的构造器
-
equals()方法
-
1 equals()的使用:
-
1.1 是一个方法,而非运算符
-
1.2 只能适用于引用数据类型
-
1.3 Object类中equals()的定义
public boolean equals(Object obj) { return (this == obj); }说明:Object类中定义的equals()和==的作用是相同的:比较两个对象的地址值是否相同。(即两个引用是否指向同一个对象实体)
-
-
-
像String、Date、File、包装类等都重写了Object类中的equals()方法。重写以后,比较的不是两个引用的地址是否相同,而是比较两个对象的"实体内容"是否相同。
-
通常情况下,我们自定义的类如果使用equals()的话,也通常是比较两个对象的"实体内容"是否相同。那么,我们就需要对Object类中的equals()进行重写。重写的原则是比较两个对象的实体内容是否相同。
5、单元测试
Java中的JUnit单元测试
- 中当前工程 - 右键择:build path - add libraries - JUnit 4 - 下一步
- 创建Java类,进行单元测试。
此时的Java类要求: 2.1此类是public的;2.2此类提供公共的无参的构造器
- 此类中声明单元测试方法。
此时的单元测试方法:方法的权限是public,没返回值,没形参
-
此单元测试方法上需要声明注解:@Test
并在单元测试类中导入:import org.junit.Test;
-
声明好单元测试方法以后,就可以在方法体内测试相关的代码。
-
写完代码以后,左键双击单元测试方法名,右键:run as - JUnit Test
6、包装类
基本数据类型<--->包装类:JDK 5.0 新特性:自动装箱与自动拆箱
基本数据类型、包装类--->String:调用String重载的valueOf(Xxx xxx)
String--->基本数据类型、包装类:调用包装类的parseXxx(String s)
注意:转换时,可能会报NumberFormatException
关键字 2: static final abstract interface
static:静态的
-
可以用来修饰的结构:主要用来修饰类的内部结构
属性、方法、代码块、内部类
-
static修饰属性:静态变量(或类变量)
-
1 属性,是否使用static修饰,又分为:静态属性 vs 非静态属性(实例变量)
实例变量:我们创建了类的多个对象,每个对象都独立的拥一套类中的非静态属性。当修改其中一个对象中的非静态属性时,不会导致其他对象中同样的属性值的修改。
静态变量:我们创建了类的多个对象,多个对象共享同一个静态变量。当通过某一个对象修改静态变量时,会导致其他对象调用此静态变量时,是修改过了的。
-
2 static修饰属性的其他说明:
-
2.1 静态变量随着类的加载而加载。可以通过"类.静态变量"的方式进行调用;
-
2.2 静态变量的加载要早于对象的创建。
-
2.3 由于类只会加载一次,则静态变量在内存中也只会存在一份:存在方法区的静态域中。
-
2.4 类变量 实例变量
? 类 yes no
? 对象 yes yes
-
-
-
static修饰方法:静态方法、类方法
-
1 随着类的加载而加载,可以通过"类.静态方法"的方式进行调用
-
2 静态方法 非静态方法
? 类 yes no
? 对象 yes yes
-
3 静态方法中,只能调用静态的方法或属性;非静态方法中,既可以调用非静态的方法或属性,也可以调用静态的方法或属性。
-
-
static的注意点:
-
1 在静态的方法内,不能使用this关键字、super关键字
-
2 关于静态属性和静态方法的使用,大家都从生命周期的角度去理解。
-
-
如何判定属性和方法应该使用static关键字
-
1 关于属性
属性是可以被多个对象所共享的,不会随着对象的不同而不同的。
类中的常量也常常声明为static
-
2 关于方法
操作静态属性的方法,通常设置为static的;
工具类中的方法,习惯声明为static的。比如:Math、Arrays、Collections类
-
单例模式
1、饿汉式
class Bank{
//1.私化类的构造器
private Bank(){
}
//2.内部创建类的对象
//4.要求此对象也必须声明为静态的
private static final Bank instance = new Bank();
//3.提供公共的静态的方法,返回类的对象
public static Bank getInstance(){
return instance;
}
}
2、懒汉式
class Order{
//1.私化类的构造器
private Order(){
}
//2.声明当前类对象,没初始化
//4.此对象也必须声明为static的
private static Order instance = null;
//3.声明public、static的返回当前类对象的方法
public static Order getInstance(){
if(instance == null){
instance = new Order();
}
return instance;
}
}
main()方法的说明
小结:一叶知秋
public static void main(String[] args){//方法体}
权限修饰符:private 缺省 protected pubilc ---->封装性
修饰符:static \ final \ abstract \native 可以用来修饰方法
返回值类型: 无返回值 / 有返回值 -->return
方法名:需要满足标识符命名的规则、规范;"见名知意"
形参列表:重载 vs 重写;参数的值传递机制;体现对象的多态性
方法体:来体现方法的功能
代码块
1、代码块的作用:用来初始化类、对象的信息
2、分类:代码块要是使用修饰符,只能使用static
3、实例化子类对象时,涉及到父类、子类中静态代码块、非静态代码块、构造器的加载顺序:由父及子,静态先行。
4、静态代码块
-
1 内部可以输出语句
-
2 随着类的加载而执行,而且只执行一次
-
3 作用:初始化类的信息
-
4 如果一个类中定义了多个静态代码块,则按照声明的先后顺序执行
-
5 静态代码块的执行要优先于非静态代码块的执行
-
6 静态代码块内只能调用静态的属性、静态的方法,不能调用非静态的结构
5、非静态代码块
-
1 内部可以输出语句
-
2 随着对象的创建而执行
-
3 每创建一个对象,就执行一次非静态代码块
-
4 作用:可以在创建对象时,对对象的属性等进行初始化
-
5 如果一个类中定义了多个非静态代码块,则按照声明的先后顺序执行
-
6 非静态代码块内可以调用静态的属性,静态的方法、或非静态的属性、非静态的方法
final 最终的
1、final 用来修饰一个类:此类不能被其他类所继承。
? 比如:String类、System类、StringBuffer类
2、final 用来修饰方法:表明此方法不可以被重写
? 比如:Object类中getClass();
3、final 用来修饰变量:此时的"变量"就称为是一个常量
- final修饰属性:可以考虑赋值的位置:显式初始化、代码块中初始化、构造器中初始化;
- final修饰局部变量:尤其是使用final修饰形参时,表明此形参是一个常量。当我们调用此方法时,给常量形参赋一个实参。一旦赋值以后,就只能在方法体内使用此形参,但不能进行重新赋值。
4、static final 用来修饰属性:全局常量
abstract 抽象的
1、可以用来修饰:类、方法
2、具体的:
-
1 abstract修饰类:抽象类
此类不能实例化、抽象类中一定有构造器,便于子类实例化时调用(涉及:子类对象实例化的全过程)开发中,都会提供抽象类的子类,让子类对象实例化,完成相关的操作,抽象的使用前提:继承性
-
2 abstract修饰方法:抽象方法
抽象方法只有方法的声明,没方法体,包含抽象方法的类,一定是一个抽象类。反之,抽象类中可以没有抽象方法的。若子类重写了父类中的所有的抽象方法后,则此子类方可实例化,若子类没重写父类中的所有的抽象方法,则此子类也是一个抽象类,需要使用abstract修饰;
3、注意点
- abstract不能用来修饰:属性、构造器等结构
- abstract不能用来修饰私方法、静态方法、final的方法、final的类
interface 接口
理解:修饰接口:public、abstract(本质上一质)、缺省的
1、接口使用interface来定义;
2、Java中,接口和类是并列的两个结构
3、如何定义接口:定义接口中的成员
-
1 JDK7及以前:只能定义全局常量和抽象方法
? 全局常量:public static final可以省略不写
? 抽象方法:public abstract可以省略不写
-
2 JDK8:除了定义全局常量和抽象方法之外,还可以定义静态方法、默认方法(略)
4、接口中不能定义构造器的!意味着接口不可以实例化
5、Java开发中,接口通过让类去实现(implements)的方式来使用;
-
1 如果实现类覆盖了接口中的所有抽象方法,则此实现类就可以实例化
-
2 如果实现类没覆盖接口中所有的抽象方法,则此实现类仍为一个抽象类
6、Java类可以实现多个接口,弥补了Java单继承性的局限性;
? 格式:class AA extends BB implements CC,DD,EE
7、接口与接口之间可以继承,而且可以多继承
类结构:内部类(类的第五个成员)
1、定义:Java中允许将一个类A声明在另一个类B中,则类A就是内部类,类B称为外部类。
2、内部类的分类:
-
1 成员内部类(静态、非静态 )
-
2 局部内部类(方法内、代码块内、构造器内)
3、成员内部类的理解:
-
1 一方面,作为外部类的成员:调用外部类的结构;可以被static修饰;可以被4种不同的权限修饰;
-
2 另一方面,作为一个类:类内可以定义属性、方法、构造器等;可以被final修饰,表示此类不能被继承。言外之意,不使用final,就可以被继承;可以被abstract修饰;
4、成员内部类:
-
1 如何创建成员内部类的对象?(静态的,非静态的)
//创建静态的Dog内部类的实例(静态的成员内部类):
Person.Dog dog = new Person.Dog();//创建非静态的Bird内部类的实例(非静态的成员内部类):
//Person.Bird bird = new Person.Bird();//错误的Person p = new Person();Person.Bird bird = p.new Bird(); -
2 如何在成员内部类中调用外部类的结构?
class Person{
String name = "小明";
public void eat(){
}
//非静态成员内部类
class Bird{
String name = "杜鹃";
public void display(String name){
System.out.println(name);//方法的形参
System.out.println(this.name);//内部类的属性
System.out.println(Person.this.name);//外部类的属性
//Person.this.eat();//外部类方法
}
}
}
5、局部内部类的使用:
//返回一个实现了Comparable接口的类的对象
public Comparable getComparable(){
//创建一个实现了Comparable接口的类:局部内部类
//方式一:
// class MyComparable implements Comparable{
// @Override
// public int compareTo(Object o) {
// return 0;
// }
// }
// return new MyComparable();
//方式二:
return new Comparable(){
@Override
public int compareTo(Object o) {
return 0;
}
};
}
6、注意点:局部内部类是指位于方法内的类,局部内部类若要访问其所在方法内的变量,则该变量必须是final修饰的。
总结:成员内部类和局部内部类,在编译以后,都会生成字节码文件。
格式:成员内部类:外部类$内部类名.clas
? 局部内部类:外部类$数字内部类名.class
匿名对象(我们创建的对象,没显式的赋给一个变量名)
特点:匿名对象只能调用一次。
举例:
new Phone().sendEmail();
new Phone().playGame();
new Phone().price = 1999;
new Phone().showPrice();//0.0
应用场景:
PhoneMall mall = new PhoneMall();
//匿名对象的使用
class PhoneMall{
public void show(Phone phone){
phone.sendEmail();
phone.playGame();
}
}
mall.show(new Phone());