一、简介
1. 什么是面向对象
OOP:Object Oriented Programming 面向对象编程;
面向对象是一种思想,使用`类` 和 `对象`的概念进行程序设计,一切皆对象
2. 两个概念
2.1 类
类是具有相同特征和行为的一组对象的抽象
2.2 对象
对象是类的具体的实例
对象是某个具体的实物,如这张桌子、张三等
3. 产生
记录马路上车辆的信息——>需要一个汽车类型,便于存储信息
自定义一个数据类型
二、类的使用
1. 定义一个类(型)
语法:
class 类名
{
成员属性;
成员方法;
}
类:一个类就是一个数据类型,定义一个类就是创建了一种数据类型
属性:类的特征,语法:数据类型 属性名;
方法:类的行为,语法:public 返回值类型 方法名(参数){ }
2. 创建对象
语法:
// 方式1
类名 对象名 = new 类名();
// 方式2
类名 对象名;
对象名 = new 类名();
3. 访问对象
为对象的属性赋值:对象名.属性名=值
获取对象的属性值:对象名.属性名
调用对象的方法:对象名.方法名()
4. 注意
在实际开发中,一个文件对应一个类,即一个类对应一个文件;
一个文件中可以包含多个类,但只能有一个public修饰的类,且此类的名称必须与文件名相同
三、this关键字
1. 全局变量和局部变量
全局变量:
- 在类中直接定义的变量,称为全局变量,也就属性
- 在整个类中都可以访问
- 有默认值,可以直接访问 String(null) int(0) double(0.0)
局部变量:
- 除了全局变量以外的其他变量,称为局部变量,如方法中或代码块中定义的变量
- 只能在局部访问,如只能在方法或代码块中使用
- 没有默认值,必须先赋值才能使用
可以使用this关键字解决局部变量和全局变量同名的问题
public static void main(String[] args) {
Car[] cars=new Car[3];
}
public static void inputInfo(Car[] cars){
//方法一:原主函数定义的数组是局部变量作为一个参数传递过来
//方法二:把数组的定义放到类体中变成全局变量 则这个函数也有访问权
}
2. this用法
this表示当前类的对象
- 只能在类的方法中使用,表示方法的调用者,即调用方法的对象
- 当局部变量和全局变量同名时,可以使用`this.`来访问全局变量
- 当局部变量和全局变量不同名时,可以省略不写this.
class Account{
double money;
public void saveMoney(double money){
this.money+=money;
}
四、static关键字
static表示静态的,可以用来修饰变量、方法等,分别称为静态变量、静态方法
1. 静态变量
使用static修饰的变量,称为**静态变量 或 类变量**
静态变量为类的所有对象所共有,属于整个类
访问方式:`对象名.属性名` 或 `类名.属性名`(推荐)
2. 静态方法
使用static修饰的方法,称为静态方法 或 类方法;
访问方式:`对象名.方法名()` 或 `类名.方法名()`(推荐);
静态方法只能访问静态变量和静态方法,不能访问实例变量和实例方法;
静态方法中不能使用this关键字,因为this表示当前类的某个对象,而静态方法不属于某个特定的对象;
变量分类:
- 从作用域上划分:全局变量、局部变量
- 从变量所属上划分:实例变量、类变量
public static void main(String args[])
{
Student.sno=18; //静态变量 所有对象都是18 先赋值后面才可以用
Student.keep(1);//s1.keep();错 访问————类名.方法名()可行
}
class Student{
static int sno;
public static void keep(int num){
System.out.println("统一学号是:"+sno);
// this.sno=num; 静态方法没办法用this 它是面向实例的 对象的 而不是类的
}
}
五、方法重载
一个类中存在两个或两个以上同名的方法,其参数不同,称为方法重载 overload
1.在同一个类中
2.方法名相同
3.参数列表不同(参数个数 参数类型 顺序至少有一项不同) 即方法签名不同
4.与方法修饰符public,返回值类型,形参名无关
调用时会根据传递的参数不同自动调用相应的最佳匹配重载函数方法(会出现自动类型转换)
作用:提供同一种功能的多种实现方式,根据调用者传递的参数来决定采用哪种方式;
class Calculator{
public void sum(double a,double b){
System.out.println(a+b);
}
public void sum(int a,int b)
{
System.out.println(a+b);
}
public void sum(int a,double b)
{
System.out.println(a+b);
}
}
六、构造方法
构造方法是一种特殊的方法,也称为构造函数 或 构造器 constructor
作用:用于创建和初始化对象
特点:
1.方法名必须和类名相同
2.没有返回值,也不能写作void
3.当创建类的对象时,会自动调用构造方法
4.一个类中至少会有一个构造方法,也可以有多个构造方法(构造方法重载)
5.如果没有自定义构造方法,则类中默认会有一个无参的构造方法
6.如果自定义了构造方法,则默认的无参构造方法就不再提供了,可以自己写无参的构造方法(强烈建议)
7.可以使用`this(参数)`调用当前类中的其他构造方法,但**只能出现在构造方法的第一行**,即必须是第一条语句(注释除外)
House(String name,int number){
this.name=name;
this.number=number;
System.out.println("调用两个参数的构造函数");
}
House(String name,int number,int holder){
this(name,number);
// 调用定义过的构造函数(必须第一行) 提高效率 调用自己 把参数传递过去
this.holder=holder;
}
七、包package
作用:
(1)区分同名的类
(2)类较多时便于管理
(3)便于访问控制
声明包:
(1)语法:`package 包名;`
(2)必须位于类的第一行
包的命名规范:
(1)采用组织的反向域名 com.itany.bbs
(2)使用小写字母,不能以点号开头或结尾
导入包:
(1)当需要使用其他包中的类时必须导入(**也可以不导入,直接类的全名**)
(2)使用import,写法 import 包名.类名;或 import 包名.*;
(3)必须位于包声明的下面
(4)不能同时导入不同包下的同名类,如java.util.Date和java.sql.Date
常用的包:
(1) java.lang 包含Java的核心类,如System,String,Math等,**该包默认会被自动导入,当使用其中的类时,无需手动导入**
(2) java.util 包含实用的工具类,如Scanner、Arrays等
八、访问修饰符
用来控制访问范围,可以修饰:变量、方法、类等
- public:在哪都能访问
- protected:只能不同包并且非子类时不能访问,其他都能访问
- default:只有本包中可以访问
- private:只有本类中可以访问
范围从大到小的顺序:public > protected > default > private
九、对象的初始化顺序
1. 类加载
概念:将class文件读取加载到JVM内存中的过程,称为类加载(由**类加载器**来完成)
类加载的时机:
1. 创建类的对象
2. 调用类的静态属性或静态方法
3. 执行main方法,main方法所在的类会被加载
4. 通过反射调用类`Class.forName("包名.类名");`
注:每个类只会被加载一次
2. 类的成员
类中的成员有:
- 属性(实例属性、静态属性)
- 方法(实例方法、静态方法)
- 构造方法
- 代码块
- 静态代码块:使用static修饰的代码块
注:static可以修饰:变量、方法、代码块、匿名类等
3. 初始化流程
步骤:
1. 对象所在的类被加载
执行静态属性和静态代码块(根据定义的属性,从上往下执行)
特性:
- 静态变量在类加载时初始化,且在内存中只分配一块空间
- 静态代码块在类加载时执行,且只执行一次,主要用于初始化静态变量
- 静态代码块不能初始化实例变量,只能初始化静态变量
2. 对象被创建
执行实例属性和代码块(根据定义的属性,从上往下执行)
执行构造方法
总结:执行的先后顺序`静态代码块>代码块>构造方法`
public static void main(String[] args) throws ClassNotFoundException {
开启此类加载器
Class.forName("four_seventh.Continue");
Continue continue1 = new Continue();
}
class Continue{
static double intervals=1;
String time="康熙年间";
{
System.out.println("普通代码块"+time);
}
static{
intervals=1.2;
System.out.println("静态方法块"+intervals);
}
Continue(){
System.out.println("调用构造方法");
}
}
静态方法块1.2
普通代码块康熙年间
调用构造方法
十、面向对象的三大特征
1. 封装
将类的属性封装在类的内部,不允许在类的外部直接访问,保护数据的安全,使内容可控
实现的步骤:
(a)将属性私有化
使用private修饰属性
(b)提供对外访问的方法,用于赋值和取值
使用public修改方法
方法名的命名规范:
- 赋值方法:以set开头,如setXxx,称为setter方法
- 取值方法:以get开头,如getXxx,称为getter方法
对于boolean类型的属性,可以使用getXxx,也可以使用isXxx
注:一般都通过开发工具自动生成setter和getter方法**
如果属性只有setter方法,则表示该属性是写的,在外部只能修改
如果属性只有getter方法,则表示该属性是只读的,在外部只能读取
2. 继承
2.1 概念
可以让一个类继承自另一个类,此时该类会继承另一个类中的属性和方法;
继承而得到的类称为子类(派生类),被继承的类称为父类(超类/基类)
继承是一种`is a`的关系,如`Cat is a Animal——>猫是动物`, 或 `Student is a Person——> 学生是人`
2.2 实现
语法:
class 子类 extends 父类
{
}
作用:
- 代码复用:将多个类中相同的属性和方法放到父类中
- 功能扩展:子类可以有自己特有的属性和方法
特点:
- Java只支持单继承,不支持多继承,但支持多层继承,即继承的传递
- Java中所有的类都直接或间接地继承自java.lang.Object类
2.3 继承的范围
子类可以继承父类的哪些成员?
1. 父类的public、protected的属性和方法可以被子类继承
2. 父类的默认修饰符的属性和方法在同包的情况下可以被子类继承
3. 父类的private的属性和方法不能被子类继承
4. 父类的构造方法不能被子类继承(原因:构造方法名必须与类名一样,而子类名称不可能与父类名称相同)
2.4 构造方法的调用
调用过程:
- 创建子类对象时默认会自动调用父类的**无参构造方法**(此时必须要保证父类中有无参构造)
- 从子类开始,逐层向上调用父类的构造方法,直到Object类,然后再层层返回到子类中,执行后续代码
- 创建子类对象时必须会调用父类的构造方法,而调用父类的构造方法也就创建了父类的对象,所以当创建子类对象时,其实也创建了父类的对象,只不过这个父类对象并不是独立存在的,而是和子类对象合为一体的
- 可以使用super关键字调用父类中的构造方法
super关键字:
- 表示父类对象的引用,只能在子类中使用
- 可以使用`super()`调用父类的构造方法,必须位于第一行
- 可以使用`super.`调用父类的属性和方法,解决父类和子类中成员同名的问题
this关键字:
- 表示当前类的对象的引用,只能在实例方法中使用
- 可以使用`this()`调用本类中重载的构造方法,必须位于第一行
- 可以使用`this.`调用本类的属性和方法,解决全局变量和局部变量同名的问题
2.5 方法重写
子类中的方法,与父类中的方法的**名称、参数列表、返回类型**一样,我们就说子类重写了父类的该方法,称为方法重写 override
- 在父子类中
- 方法名相同
- 参数列表相同
- 返回类型相同或是其子类
- 访问修饰符不能缩小,即访问权限不能缩小
- 子类不能抛出比父类更大的异常(后面会讲)
作用:用来重新定义子类的行为,解决父类和子类的差异性
**当重写方法后,子类调用的是重写后的方法**
3. 多态
3.1 概念
多态是具有表现多种形态的能力,简单来说就是一种事物,具有多个形态
回顾:**基本数据类型之间的转换:**
- 自动类型转换
- 强制类型转换
引用类型之间的转换
3.2 引用类型之间的转换
两种:
- 自动类型转换
将子类对象转换为父类,如teacher ——> people
将父类的引用 指向 子类的对象,称为**向上转型**,会自动进行类型转换
特性:
(a)通过父类引用变量调用的方法 是 子类重写后的方法,不是父类的方法
(b)通过父类引用变量无法访问 子类特有的属性和方法
- 强制类型转换
将一个指向子类对象的父类引用 赋给一个子类的引用,称为**向下转型**,必须进行强制类型转换
语法:`(子类类型)指向子类对象的引用`
特性:
(a)向下转型后,可以访问子类特有的属性和方法
(b)必须转换为父类指向的真实子类类型,否则会报错ClassCastException类型转换异常
(c) 向下转换是不安全的,可以在转换前使用`instanceof`操作符判断对象的类型,避免类型转换异常
3.3 多态的实现
将父类作为方法形参,将子类的对象作为方法实现,从而实现多态
案例: 主人、宠物
3.4 总结
实现多态的条件:
(a)继承的存在(继承是多态的基础,没有继承就没有多态)
(b)子类重写父类的方法(多态下调用的是子类重写后的方法)
(c)父类引用指向子类对象(将子类对象传给父类引用)
多态的优点:
(a)减少代码量
(b)提高可扩展性和可维护性
public class 三大特征 {
static Master master=new Master();//静态方法不能访问非静态变量
public static void main(String[] args) {
menue();
}
public static void menue(){
System.out.println("欢迎您来到宠物店!");
System.out.println("请选择要领养的宠物类型:");
System.out.println("1.狗2.猫3.猪");
Scanner input=new Scanner(System.in);
int choice=input.nextInt();
Pet pet=getChoice(choice);
System.out.println("领养宠物成功!");
master.feed(pet);
}
将父类的引用作为方法的返回值类型
public static Pet getChoice(int choice){
Pet pet=null;//局部变量默认没有初始值 赋空值则可以返回Pet
switch(choice){
case 1:
pet=new Dog("Lucky",90,"阿拉斯加狗");
break;
case 2:
pet=new Cat("flex",80,"pink");
break;
case 3:
pet=new Pig();
break;
default:
System.out.println("输入错误");
}
return pet;
}
}
class Pet{
String name;
int index;
public Pet() {
}
public Pet(String name, int index) {
this.name = name;
this.index = index;
}
public void eat(){
System.out.println("宠物正在吃饭");
}
}
class Dog extends Pet{
String breed;
public Dog(String name, int index,String breed) {
super(name,index);
this.breed = breed;
}
@Override
public void eat() {
if(this.index<100){
index+=4;
System.out.println(name+"这只狗正在吃饭");
}else{
System.out.println(name+"这只狗吃饱了");
}
}
}
class Cat extends Pet{
String color;
public Cat(String name, int index,String color) {
super(name,index);
this.color = color;
}
@Override
public void eat() {
System.out.println(name+"这只猫正在吃饭");
index+=6;
}
}
class Pig extends Pet{
}
class Master{
String name;
Master() {
}
Master(String name) {
this.name = name;
}
将父类的引用作为方法的形参
public void feed(Pet pet){
pet.eat();
}
}
十一.关键字
1.final
final表示最终的,用来修饰变量、方法、类等
1. 修饰变量
被final修饰的变量,称为常量 constant,常量的值不能被修改
被static final修饰的变量,称为静态常量,一般也称为常量(使用较多)
常量的命名规范:所有字母都大写,多个单词之间以下划线连接
应用:一般用于替代`僵尸代码` 或 `死代码`,解决可读性问题
2. 修饰方法
被final修饰的方法,不能被重写
3. 修饰类
被final修饰的类,不能被继承,即不能有子类
4. 修饰参数
被final修饰的参数,只能读取,不能修饰
public class final关键字 {
无static是某个实例所有;有static是这个类公有 可以修改
static final int b=1;
static final int c;
static{//在类加载的时候初始化
c=12;
}
public static void main(String[] args) {
final int a=2;
redFlower redFlower = new redFlower();
redFlower.print();
}
}
final class book{
}
/*class math extends book{
}*/
class Flower{
int number;
String color;
public final void show(){
System.out.println("快来花圃看看!");
}
public void print(){
System.out.println("颜色");
}
}
class redFlower extends Flower{
public void print(){
System.out.println("红色");
}
/*public void show(){
System.out.println("look");
}*/
}
2.abstract
1.概念
被abstract修饰的类,称为抽象类
该类不能通过new来创建对象,只能被继承
被abstract修饰的方法,称为抽象方法
该方法只有声明,没有具体实现,即没有方法体{},以分号结尾
2.特性
抽象类中可以有抽象方法,也可以没有抽象方法
含有抽象方法的类,必须为抽象类
子类继承抽象类后,必须重写/实现抽象类中所有的抽象方法,否则子类仍然为抽象类
抽象方法中可以有构造方法,但不是用来创建对象的,而是用来初始化属性的
abstract class Pet{
String name;
int age;
Pet(String name){//用来初始化属性的 下面super呼应
this.name=name;
}
public abstract void show();//子类都是要重写的
}
class rabbit extends Pet{
rabbit(String name) {
super(name);
}
public void show(){
System.out.println("这是兔子");
}
public void print(){
System.out.println("既然是抽象方法就要在继承的子类中实现出来");
}
}
这是一边看视频一边学习的笔记-借用了一些老师的笔记内容-如有侵权,通知删除!
新手小白学习之路~~~