面向对象
01_什么是面向对象
面向过程&面向对象
-
面向过程思想
-
步骤清晰简单,第一步做什么,第二步做什么……
-
面向过程适合处理一些简单的问题
-
-
面向过程思想
-
物以类聚,分类的思维模式,思考问题首先会解决问题需要哪些分类,然后对这些分类进行单独思考。最后,才对某个分类下的细节进行面向过程的思索
-
面向对象适合处理复杂的问题,适合处理需要多人协作的问题!
-
-
对于描述复杂的事物,为了从宏观上把握、从整体上分析,我们需要使用面向对象的思路来分析整个系统。但是,具体到微观操作,任然需要面向过程的思路去处理。
什么是面向对象
-
面向对象编程的本质就是:以类的方式组织代码,以对象的组织(封装)数据
-
抽象(抽取出相似的共同点)
-
三大特性:封装、继承、多态
-
从认识论角度考虑是先有对象后有类。对象,是具体的事物。类,是抽象的,是对对象的抽象
-
从代码运行角度考虑是先有类后有对象。类是对象的模板。
02_回顾方法
静态方法:添加了static的方法就是静态方法
静态方法可以通过类名.方法名
直接调用
非静态方法:没有static的方法
//需要实例化这个类 new
//假设add类中有一个dog非静态方法,如何调用?
add add=new add();
//直接调用
add.dog();
对象类型 对象名=对象值
静态方法不能调用非静态方法,非静态方法同理。
静态方法是和类一起加载的,而非静态方法是在类实例化之后才存在的。
形参只是一个形式的存在,并没有正式的值。而实参就是它正式的值。
03_类与对象
类是一中抽象的数据类型,它是对某一类事物整体描述/定义,但是并不能代表一个具体的事物。
例:动物、植物、手机、电脑……
它们并不指的是一个具体的事物
对象是抽象概念的具体实例
例:张三就是人的一个具体实例,
能够体现出特点,展现除功能的是具体的实例,而不是一个抽象的概念。
类是抽象的,它需要实例化
类实例化后会返回一个自己的对象!
04_构造器
使用new关键字创建的时候,除了分配内存空间之外,还会给创建好的对象进行默认的初始化以及对类中构造器的调用。
//无参构造
public Person(){}
//有参构造
public Person(String name,int age){
this.name=name;
this.age=age;
}
构造器也称为构造方法,是在进行创建对象的时候必须要调用的。并且构造器有以下两个特点:
-
必须和类名相同
-
必须没有返回值,也不能写void
作用:
-
new 的本质在调用构造方法
-
初始化对象的值
注意点:
-
定义有参构造之后,如果想使用无参构造,必须显示的定义一个无参构造
一个构造器即使什么都不写,它也会存在一个方法
pet dog=new pet();
pet cat=new pet();
//这里的cat、dog都是引用变量名,它们在栈中只有一个地址值,实际的数据存放在堆中
05_小结
-
类与对象
类是一个抽象的模板,对象是一个具体的实例
-
对应的引用
基本类型:8种
引用类型:对象是通过引用来操作的,在栈中的数据都是地址值,实际数据存储在堆中
-
属性、字段Field、成员变量
修饰符 属性类型 属性名=属性值
-
对象的创建和使用
必须使用new关键字以及构造器,Person pe=new Person();
对象的属性:pe.name;
对象的方法:pe.sleep();
-
类的组成:
静态的属性:成员变量
动态的行为:方法
06_封装
程序设计要追求“高内聚,高耦合”,高内聚就是类的内部数据操作细节自己完成,不允许外部干涉;低耦合指仅暴漏少量的方法留给外部使用。
封装(数据的隐藏)
通常,应禁止直接访问一个对象中数据的实际表示,而应通过操作接口来访问,这称为信息隐藏。
属性私有:get/set
get用来获取这个数据 set给这个数据设置值
// set获取数据的时候可以给数据进行检测,如果遇到不合法的数据直接筛出。
// 下面的例子中,设置的年龄不能大于100,不能小于0,如果大于或小于了设置的数值,则会返回指定的内容
//a类
private int age;
public int getAge() {
return age;
}
public void setAge(int age) {
if (age < 100 && age > 0) {
this.age = age;
} else {
System.out.println("年龄错误!");
}
}
//b类
aa.setAge(101); //set输入值
System.out.println(aa.getAge()); //这个值在父类中转一圈后返回到get方法中
//输出结果为:年龄错误!
07_继承
继承的本质是对某一批类的抽象,从而实现对现实世界更好的建模
extends的意思是“扩展”,子类是父类的扩展。
java中只有单继承,没有多继承!
继承是类和类之间的一种关系,除此之外,类和类之间的关系还有依赖、组合、聚合等。
继承关系的两个类,一个为子类(派生类),一个为父类(基类)。子类继承父类,使用关键字extends表示。
子类和父类之间,从意义上讲应该具有“is a“的关系。
-
object类
所有的类都直接或间接的继承了object类
-
super
0.super是可以调用父类的方法以及属性
-
super调用父类的构造方法,必须在构造方法的第一个
-
super必须只能出现在子类的方法或者构造方法中。
-
super和this不能同时调用构造方法。
VS this:
-
代表的对象不同:
this:本身调用者的对象
super:代表父类对象的引用
-
前提:
this:没有继承也能使用
super:只能在继承条件才可以使用
-
构造方法:
this:本类的构造
super:父类的构造
-
-
方法重写(Override)
重写需要有继承关系,子类重写父类的方法
-
方法名必须相同
-
参数列表必须相同
-
修饰符:范围可以扩大但不能缩小
-
抛出的异常:范围可以缩小,但不能扩大;
-
08_多态
//假设Student继承Teacher
//Teacher中只有一个方法
public void san(){System.out.println("a");}
//Student中的方法
public void san() {System.out.println("b");}
//测试的main方法
public static void main (String[] args){
Student a = new Student();
Teacher b = new Student();
a.san();
b.san();
}
//输出结果
a
a
//如果Student与Teachar中的方法添加static的结果
a
b
//结果
//多态就是方法的多样性,改变static和调用的数据类型可以输出不同的结果
多态注意事项:
-
多态是方法的多态,属性没有多态
-
存在条件:继承关系,方法需要重写,父类引用指向子类对象! F f1=new s();
-
方法调用错误,会报出异常,ClassCastException!
以下方法无法重写,也无法使用多态:
-
static:它属于类,不属于实例
-
final:常量,即在常量池中,无法修改
-
private:私有方法,无法重写
-
//假设f类继承了s类
f f=new f();
s ff=new f();
System.out.println(s instanceof f);
System.out.println(s instanceof s);
//可以判断是否属于继承父子关系
Student s22=(Student)s2;//方法1
s22.sum();
((Student)s2).sum();//方法2
//这个方法使用了强制类型转换,修改了s2的类型,从Person修改成Student。
特点:
-
父类引用指向子类对象
-
把子类转换为父类,向上转型
-
把父类转换成子类,向下转型:强制转换
-
方便方法的调用,减少重复的代码!
子转父:向上转型,直接转,丢失子类中原本可直接调用的特有方法;
父转子:向下转型,会丢失父类被子类所重写掉的方法。
09_static静态关键字
static是静态的,被他所修饰的将与类一起加载
{//匿名代码块
System.out.println(1);
}
static {//静态代码块
System.out.println(2);
}
//输出结果为2
//静态的会和类一起加载,它会在匿名代码块前面
private static int age=1500; //静态的变量
private int age1=2000; //非静态的变量
test s1= new test(); //创建对象
System.out.println(s1.age);
System.out.println(s1.age1); //通过对象可以正常输出
System.out.println(test.age); //通过类名可以输出被修饰的变量
System.out.println(test.age1); //而没有被修饰的则无法通过类名调用
可以通过Math.random;导入随机数
System.out.println(Math.random());
//如果觉得麻烦,可以通过静态导包
import.static java.lang.Math.random;
System.out.println(random());
//这样可以省去写Math
10_抽象类
abstract修饰符可以用来修饰方法也可以修饰类,如果修饰方法,那么该方法就是抽象方法;如果修饰类,呢么该类就是抽象类。
抽象类中可以没有抽象方法,但是有抽象方法的类一定要声明为抽象类。
抽象类不能使用new关键字来创建对象,它是用来让子类继承的。
抽象方法,只有方法的声明,没有方法的实现,它是用来让子类实现的。
子类继承抽象类,那么就必须要实现抽象类没有实现的抽象方法,否则该子类也要声明为抽象类。
实现(implements)
实现一个方法,在实现某个接口,或者是继承某个抽象类,在接口和在抽象类中定义的方法,本身是没有实现的,也就是没有方法体,你在当前类中就需要去实现这个方法。
重写(overloading)
重写一个方法的话,就是在集成的父类中有个完整的方法,而你并不打算使用它或者需要做一点修改来达到某个目的,所以需要重写,常见的是重写Object中的toString()这个方法了.
简单来说,有方法体的叫重写,没有方法体的叫实现。
11_接口
一、接口是什么?
接口是抽象的抽象(抽象类是具体的抽象)。
例如制作一款运动手表,接口就是产品需要实现的功能。我这款手表要实现与APP的结合,要实现来电的提醒,要实现闹铃的设置,要实现心率的实时监控,要实现步数的记录...... 我不会告诉你任何具体的实现方法,我只会给你一个产品功能的框架,而如果你是我团队的一员,要来制作这款运动手表,那么你就一定要把我定义的内容全部实现。
即“如果你是......, ,就必须......”
这就是接口,在程序中,它就相当于是一个类的行为规范。
接口类名与实现:通常在接口类名后加上Impl来表示这个接口类的实现
二、接口的作用?
-
有利于代码的规范
-
有利于代码进行维护
-
有利于代码的安全和严密
-
丰富了继承的方式
三 、接口的相关语法
//接口声明
//关键字:interface
public interface 接口名 {}
//接口体
1. 常量(没有变量)
( public static final ) int MAX = 100; 可以省略public static final
2. 抽象方法
(public abstract) void add();可省略public abstract
常量和抽象方法都只有一种访问修饰符:public
接口默认提供 public,static,final,abstract 关键字
接口的实现
关键字:implements
1. 类可以实现一个或多个接口
public class Doglmpl implements Dog,Sleepable
Dog 也可以继承一个具体类
public class Doglmpl extends Animal implements Dog, Sleepable
2. 类中必须实现接口中的全部方法(抽象类可只实现接口中的部分方法)
3. 类中重写的方法,访问修饰符必须是 public
4. 接口中定义的常量,在继承了接口的类中可以直接使用。
5. 接口可以实现伪多继承
6. 接口不能被实例化,它没有自己的实现方法与构造方法,只有抽象方法
接口间的继承
public interface A{}
public interface B extends A{}
// 接口B继承的A
小结:
-
接口就是一个规范
-
接口使用interface声明:public interface a{}
-
接口继承使用implements关键字,接口可以实现多继承:
public class A implements B,C {}
-
实现类中必须重写接口的全部方法
-
接口可以继承接口
12_内部类
内部类就是在一个类中再定义一个类,例如在a类中定义了一个b类,那么a就是外部类,b是内部类。
1.内部类有四种:
-
成员内部类
public class Outer { private int id=10; public void out(){ System.out.println("这是外部类"); } public class Inner { public void in(){ System.out.println("这是内部类"); } public void getID(){ //内部类可以调用外部类的私有属性 System.out.println(id); } } }
-
静态内部类
用static修饰的类叫静态内部类,它不能使用外部类的属性与方法
-
局部内部类
class B{ public void eat(){ //局部内部类,在类中方法再次定义的类 class b{ }}}
-
匿名内部类
public class test { public static void main(String[] args) { //匿名内部类,没有名字初始化类,不用将实例保存在变量中 new a().eat(); } } class a{ public void eat(){ System.out.println("1"); } }
-