面向对象和面向过程的区别:
问题: 冰箱里面放有脏衣服,怎么洗干净?
面向过程:
1 执行加洗衣粉方法;
2 执行加水方法;
3 执行洗衣服方法;
4 执行清洗方法;
5 执行烘干方法;
----------解决问题 拆成一个个方法,是没有对象去调用的。 通过一个个方法的执行解决问题。
面向对象(oop语言三大特性:继承,封装,多态): 我先搞个洗衣机对象和人对象
洗衣机: 加入一些属性和方法 洗衣服方法 清洗方法 烘干方法 人:加洗衣粉方法 加水方法
然后 人.加洗衣粉 人.加水 洗衣机.洗衣服 洗衣机.清洗 洗衣机.烘干
----------同样解决问题 先抽象出对象,然后用对象执行方法的方式解决问题。
以上例子来自:https://blog.csdn.net/xmh594603296/article/details/79774167
面向对象编程包含了:包,继承,组合,多态,抽象类,接口
一.包
1.使用包的主要目的就是保证类的唯一性,不然同样的类名出现在同一个包中会产生冲突!
2.有了包后,我们就可以导入包中的类,使用import语句导入类。
注意:在导入类的时候建议显示的指定导入的类名,防止发生冲突!
例如:
import java.util.*;
import java.sql.*;
public class Test{
public void main(String[]args){
//util和sql都存在Date类,不能识别是谁的Date类,此时会出现编译错误
Date date=new Dtae();
//如果用的是java.util的Date类,应该这样写
//java.util.Date date=new java.util.Date();
System.out.println(date.getTime());
}
}
二.继承
1.继承是一种is a语义,如下例代码中,我们来创建一个面条类,刀削面和炸酱面都属于面条,就是说他们都是面条类中的一种,所以他们之间必定会存在相同的属性和方法,我们要是不使用继承,就得为他们每一个类都进行定义属性和方法,但是他们的属性和方法会存在相同的,这就造成了大量的冗余,此时我们就应该引入继承,以达到代码的复用。
被继承的类被称作父类,基类或继承者超类,继承者被称作
子类或派生类
public class Noodles {
public String name;
public int length;
public int width;
public Noodles(){
}
public Noodles(String name,int length,int width){
this.name=name;
this.length=length;
this.width=width;
}
public void makeNoodlesStep(){
System.out.println("1.和面");
System.out.println("2.切面");
System.out.println("3.煮面");
}
public void taste(){
System.out.println(this.name+"尝起来真不错");
}
public void shape(){
}
}
class DaoXiaoMian extends Noodles{
//子类继承父类后,继承的是除父类构造方法之外的所有东西
//继承后的第一步就是帮助子类构造父类super(),目的就是为了获得父类的属性
public String color;
public DaoXiaoMian(){
}
public DaoXiaoMian(String name,int length,int width,String color){
super( name,length,width);
this.color=color;
}
public void disPlay(){
System.out.println(this.name+" "+this.length+" "+this.width+" "+this.color);
}
public void func(){
super.makeNoodlesStep();
}
public void shape(){
System.out.println("宽大的");
}
}
class ZhaJiangMian extends Noodles{
public String color;
public ZhaJiangMian(){
}
public ZhaJiangMian(String name,int length,int width,String color){
super(name,length,width);
this.color=color;
}
public void disPlay2(){
System.out.println(this.name+" "+this.length+" "+this.width+" "+this.color);
}
public void shape(){
System.out.println("细小的");
}
}
2.继承的目的:
是为了代码的复用
3.继承语法规则:
class 子类 extends 父类{
}
注意:
1.一个子类只能继承一个父类
2.继承的内容是:除父类构造方法外的所有东西
3.继承后的子类应当使用使用super关键字帮助子类构造父类
三.访问权限:
java中对于字段和方法共有四种访问权限:public,protected(专门是为了继承),default(包访问权限),private
1.private:
-
同一个包中同一个类中可以访问
-
同一个包中不同类不可以访问
-
不同包中的子类不可以访问
-
不同包中的非子类不可以访问
2.default: -
同一个包中同一个类中可以访问
-
同一个包中不同类可以访问
-
不同包中的子类不可以访问
-
不同包中的非子类不可以访问
3.protected: -
同一个包中同一个类中可以访问
-
同一个包中不同类可以访问
-
不同包中的子类可以访问
-
不同包中的非子类不可以访问
4.public: -
同一个包中同一个类中可以访问
-
同一个包中不同类可以访问
-
不同包中的子类可以访问
-
不同包中的非子类可以访问
四.final关键字
1.被final所修饰的变量是常量,只能被赋值一次,不可改变
2.被final所修饰的类不能被继承
3.被final所修饰的方法不能重写
五.多态
public class Shape {
public void draw(){
}
}
class Rect extends Shape{
@Override
public void draw() {
//super.draw();
System.out.println("正方形");
}
}
class Cycle extends Shape{
@Override
public void draw() {
//super.draw();
System.out.println("圆形");
}
}
class Triangle extends Shape{
@Override
public void draw() {
//super.draw();
System.out.println("三角形");
}
}
public class TestShape {
public static void drawMap(Shape shape){
shape.draw();
}
public static void main(String[] args) {
Rect rect=new Rect();
Cycle cycle=new Cycle();
Triangle triangle=new Triangle();
drawMap(cycle);
drawMap(rect);
drawMap(triangle);
}
}
通俗来讲多态的意思就是一种事物多种形态,比如我们生活中,打游戏时,对于游戏A来说键盘上某个按键是漂移,而对于游戏B来讲,此按键可能就是开枪。
1.多态存在的必要条件:
- 要有继承
- 要有重写
这里要区别重写与重载
重写:override
方法名相同,参数列表相同,返回值类型相同
重写注意事项:
方法不能是private
子类的方法权限一定要大于等于父类的方法权限
重写的方法不能是静态的
重载:overload
方法名相同,参数列表不同,返回值不做要求
- 父类引用指向子类对象
2.多态的转型:分为两种,xiangshangzhuanxinghexiangxia
向上转型和向下转型
- 向上转型
1.向上转型是子类的值给父类的过程,父类引用变量引用子类对象,当发生向上转型时父类只能调用自己的方法和属性。
- 多态本身就是向上转型的过程
语句:父类类型 变量名=new 子类类型()
向上转型的三种方式:直接传值,方法传参,方法返回
直接传值:
Animal animal=new Cat();
方法传参:
public class TestShape {
public static void drawMap(Shape shape){
shape.draw();
}
public static void main(String[] args) {
Rect rect=new Rect();
Cycle cycle=new Cycle();
Triangle triangle=new Triangle();
drawMap(cycle);
drawMap(rect);
drawMap(triangle);
}
}
方法返回
public class Animal2 {
public String name;
public int age;
public Animal2(){
eat();//
}
public Animal2(String name,int age){//创建一个对象分为了两步:
//1.分配内存
//2.调用构造方法
//构造方法的目的就是为了对成员属性进行初始化
this.name=name;
this.age=age;
//System.out.println("Animal(String,int)");
}
public void eat(){
System.out.println("Animal:eat()");
}
}
class Cat2 extends Animal2{
public String sex;
public Cat2(){
}
public Cat2(String name,int age,String sex){
super(name,age);//显示调用父类的构造方法
this.sex=sex;
//System.out.println("Cat(String,int,String)");
}
public void jump(){
System.out.println(this.name+"跳");
}
public void eat(){
System.out.println(this.name+"Cat:eat()");
}
}
class Bird extends Animal2{
public String color;
public Bird(String name,int age,String color){
super(name,age);//显示调用父类的构造方法
this.color=color;
}
public void fly(){
System.out.println(this.name+"fly()");
}
}
public class TestAnimal2 {
public static void main(String[] args) {
Animal2 animal2=func();
animal2.eat();
/*Cat2 cat2=new Cat2();
func(cat2);*/
}
public static Cat2 func(){//多态:方法返回法
Cat2 cat2=new Cat2("咪咪",12,"母");
return cat2;
}
}
- 向下转型:
进行向下转型之前必须的有向上转型,向下转型是强制转换
语句:**子类类型 变量名=(子类类型) 父类类型变量名 **
向下转型适用于要使用子类特有的方法(功能)时
注意:在使用多态后的的父类引用变量调用方法时会调用子类重写后的方法。
public class B {
public int num;
public B(int num){
func();
this.num=num;
}
public void func(){
System.out.println(this.num+"B.func()");
}
}
class D extends B{
public D(int num){
super(num);
}
@Override
public void func() {
System.out.println(this.num+"D.func()");
}
}
public class TestB {
public static void main(String[] args) {
B b=new D(1);
b.func();
}
}
//打印结果
//0D.func()
//1D.func()
在进行向下转型之前
3.多态的技术实现:动态绑定
运行时绑定的过程我们称之为多态。通俗易懂的讲,就是在编译的时候用的是父类中的方法,但是在运行时用的是子类的方法,也就是运行时动态绑定
在执行期间判断所引用对象的实际类型,再根据其实际类型调用所对应的方法。java中除了static方法和final方法(包含private)外其余方法均为动态绑定;
static是因为方法跟类本身绑定,与对象无关因此无论引用指向的对象是什么类型调用static方法时始终调用的是父类对应的方法;
final是因为final方法不可以被覆盖也即不可被重写,因此无法实现动态绑定;
4.多态的作用:消除类型间的耦合关系
5.使用多态的好处:
- 类调用者对类的使用成本降低
·封装是让类的调用者不需要知道类的具体实现细节
·多态是让类的调用者连这个类的类型是什么都不用知道,只用知道对象有哪些具体的方法即可
2.能够降低代码的圈复杂度,避免使用大量的if else语句
什么叫 “圈复杂度” ?
圈复杂度是一种描述一段代码复杂程度的方式. 一段代码如果平铺直叙, 那么就比较简单容易理解. 而如果有很
多的条件分支或者循环语句, 就认为理解起来更复杂.
因此我们可以简单粗暴的计算一段代码中条件语句和循环语句出现的个数, 这个个数就称为 “圈复杂度”. 如果一
个方法的圈复杂度太高, 就需要考虑重构.
不同公司对于代码的圈复杂度的规范不一样. 一般不会超过 10
3.可扩展能力强
六.this和super关键字的区别
1.this:
概念:访问本类中的属性和方法
查找范围:先查找本类,如果本类没有,就调用父类的属性和方法
特殊意义:this代表当前对象的引用
2.super:就是为了继承,继承后用super关键字帮助子类构造父类
通过子类来访问父类的属性和方法
七.抽象类:
1.包含abstract:抽象方法的类叫做抽象类
2.抽象类不能被实例化
3.抽象类 当中可以有抽象方法,也可以有非抽象方法,成员变量,
4.抽象类就是为了继承
5.抽象类被继承后一定要重写抽象方法
6.抽象类A继承了抽象类B,那么抽象类A可选择重写或者不重写抽象方法
7.抽象类如果被抽象类继承后,父类中的方法被重写了,那么另一个不是抽象类的类继承他后可以不选择重写,否则必须重写
8.抽象类的方法不能使private
语法规则:
abstract class Shape {
public abstract void draw();//类中类中包含抽象方法,那么这个类必须是抽象类
}
abstract class Rect extends Shape{
}
public class TestShape{
public static void main(String []args){
//Shape shape=new Shape();//编译错误,抽象类不能实例化
}
}
八.接口
接口比抽象类更加抽象,抽象类还可以包含非抽象方法,字段,而接口里的方法都是抽象方法,接口内只能包含静态常量。
·定义接口:
1.关键字:interface
interface ISkillOne{
void show1();
}
interface ISkillTwo{
void show2();
}
interface ISkillThree{
void show3();
}
2.接口当中的方法都不能有具体的实现,都是抽象方法–默认public abstract
interface ISkillOne{
void show1();//接口当中的方法都不能有具体的实现
}
3.接口当中的方法尽量简洁
4.接口当中的成员变量为public static final 必须进行初始化
5.接口不能被实例化
6.接口存在的意义:被继承
·实现接口:
1.关键词;implements: 实现接口
2.类与接口的关系:实现
2.接口与接口的关系:继承。两个接口的方法都要重写!
//这里类实现了三个接口,所以三个接口中的方法都要重写
class Hero1 extends Heros implements ISkillOne,ISkillTwo,ISkillThree{
public Hero1(String name, String type, String sex) {
super(name, type, sex);
}
public void disPlay(){
System.out.println("["+this.name+","+this.type+","+this.sex+"]");
}
@Override
public void show1() {
System.out.println(this.name+"一技能");
}
@Override
public void show2() {
System.out.println(this.name+"二技能");
}
@Override
public void show3() {
System.out.println(this.name+"大招");
}
}
3.接口也可发生向上转型
发生向上转型有三种方式:
直接赋值
ISkillOne skillOne=new Hero1("女娲","法师","女");//向上转型
方法传参
方法返回
4.接口是为了实现多继承,一个类只能继承一个类,但一个类可以实现多
个接口
import java.util.Arrays;
interface ISkillOne{
void show1();
}
interface ISkillTwo{
void show2();
}
interface ISkillThree{
void show3();
}
//父类
class Heros{
public String name;
public String type;
public String sex;
public Heros(String name, String type, String sex) {
this.name = name;
this.type = type;
this.sex = sex;
}
@Override
public String toString() {
return "Heros{" +
"name='" + name + '\'' +
", type='" + type + '\'' +
", sex='" + sex + '\'' +
'}';
}
}
//子类继承了Heros父类但是实现了
//ISkillOne,ISkillTwo,ISkillThree三个接口
class Hero1 extends Heros implements ISkillOne,ISkillTwo,ISkillThree{
public Hero1(String name, String type, String sex) {
super(name, type, sex);
}
public void disPlay(){
System.out.println("["+this.name+","+this.type+","+this.sex+"]");
}
@Override
public void show1() {
System.out.println(this.name+"一技能");
}
@Override
public void show2() {
System.out.println(this.name+"二技能");
}
@Override
public void show3() {
System.out.println(this.name+"大招");
}
}
class Hero2 extends Heros implements ISkillOne,ISkillTwo,ISkillThree{
public Hero2(String name, String type, String sex) {
super(name, type, sex);
}
public void disPlay(){
System.out.println("["+this.name+","+this.type+","+this.sex+"]");
}
@Override
public void show1() {
System.out.println(this.name+"一技能");
}
@Override
public void show2() {
System.out.println(this.name+"二技能");
}
@Override
public void show3() {
System.out.println(this.name+"大招");
}
}
class Hero3 extends Heros implements ISkillOne,ISkillTwo,ISkillThree{
public Hero3(String name, String type, String sex) {
super(name, type, sex);
}
public void disPlay(){
System.out.println("["+this.name+","+this.type+","+this.sex+"]");
}
@Override
public void show1() {
System.out.println(this.name+"一技能");
}
@Override
public void show2() {
System.out.println(this.name+"二技能");
}
@Override
public void show3() {
System.out.println(this.name+"大招");
}
}
public class TestDemo04 {
public static void main(String[] args) {
/* Heros[] heros=new Heros[3];
heros[0]=new Hero1("白起","坦克","男");
heros[1]=new Hero2("百里守约","射手","男");
heros[2]=new Hero3("王昭君","法师","女");
System.out.println(Arrays.toString(heros));
ISkillOne skillOne1= (ISkillOne) heros[0];
skillOne1.show1();
ISkillTwo skillTwo1= (ISkillTwo) heros[0];
skillTwo1.show2();
ISkillThree skillThree1= (ISkillThree) heros[0];;
skillThree1.show3();
ISkillOne skillOne2= (ISkillOne) heros[1];
skillOne2.show1();
ISkillTwo skillTwo2= (ISkillTwo) heros[1];
skillTwo2.show2();
ISkillThree skillThree2= (ISkillThree) heros[1];;
skillThree2.show3();
ISkillOne skillOne3= (ISkillOne) heros[2];
skillOne3.show1();
ISkillTwo skillTwo3= (ISkillTwo) heros[2];
skillTwo3.show2();
ISkillThree skillThree3= (ISkillThree) heros[2];;
skillThree3.show3();*/
ISkillOne skillOne=new Hero1("女娲","法师","女");
skillOne.show1();
}
}
5.接口的语义:一个类具有***特性
九.抽象类与接口核心区别:
抽象类可以包含普通字段和方法, 抽象类中的普通方法和字段可以直接被子类使用(不必重写),而接口中要被实现,那么接口中的方法必须需重写