当前位置: 首页 > web >正文

Java-面向对象编程

面向对象

面向对象是Java核心的内容部分,在学习的过程中首先需要掌握各种知识点,利用知识点进行程序的设计。面向对象的运用是一个漫长的过程,关系到程序设计的各个方面,不仅仅是编写代码部分。

面向对象的相关内容是比较抽象的,掌握的难度上会有所增加。

三大特征

  • 封装:核心思想就是**“隐藏细节”、“数据安全”**,将对象不需要让外界访问的成员变量和方法私有化,只提供符合开发者意愿的公有方法来访问这些数据和逻辑,保证了数据的安全和程序的稳定。所有的内容对外部不可见。

  • 继承:子类可以继承父类的属性和方法,并对其进行拓展。将其他的功能继承下来继续发展 。

  • 多态:同一种类型的对象执行同一个方法时可以表现出不同的行为特征。通过继承的上下转型、接口的回调以及方法的重写和重载可以实现多态。方法的重载本身就是一个多态性的体现。

三大思想

面向对象思想从概念上讲分为以下三种:OOA、OOD、OOP

  • OOA:面向对象分析(Object Oriented Analysis)

  • OOD:面向对象设计(Object Oriented Design)

  • OOP:面向对象程序(Object Oriented Programming )

举例:

Scanner   sc = new  Scanner(System.in);分析:1Scanner 就是Java中的一个class类。2new 关键字的含义。 ----new其实就是在堆内存中开辟空间创建对象。3Scanner(System.in); ---- 是啥?答:调用Scanner类的构造,创建出sc这个对象。System.in仅仅是提供的一个参数而已!4、通过调用sc对象中的各种方法来扫描控制台不同类型的数据。   

类的定义

类的定义

在Java语言中,class类是最为基本的单元。类:其实就是针对某一类事物的抽象描述,是一个模板。

类的设计语法、

类的修饰符使用的对象
public(公开的)类,接口,变量,方法(使用最广)
private(私有的)变量,方法,注意:不能修饰类(外部类)
default (默认的)类,接口,变量,方法
protected(受保护的)变量,方法,注意:不能修饰类(外部类)
类的修饰符   class   类名{}   

说明:

1、类的修饰符:public(缺省) 、abstract 、 final

2、class:是定义类的关键字;

3、类名:符合标识符的定义规范(首字母大写,多个单词合并则每个单词的首字母大写【参考源码】);

4、{ } : 类的主体部分,称为“类体”;

从以上的语法分析中,我们可以看出,设计一个类的外壳的时候,我们只需要关注各种修饰符即可。

public 、 缺省(不写) : 属于权限修饰符;

public  class   MyClass{}说明:MyClass这个类可以在一个Java项目中的任意的位置进行使用;class   MyClass{}说明:MyClass这个类只能是在同一个包package下可以进行使用;

在项目开发中,可以适当的借助于不同的权限修饰符,来针对我们的类进行隔离。

abstract 、 final :属于具有特殊含义的修饰符;

abstract : 修饰一个类的时候,表示这个类是一个“抽象类”。final :修饰一个类的时候,表示这个类是不允许被继承的(不允许作为父类)。源码中的String类就是这样设计的:     源码  public final class String

注意!

abstract 和 final 是不能同时搭配使用的;

在Java语言中,有一个永恒成立的等式:

java类 = 属性  +  方法换言之: 类 是由属性 和 方法所构成的 ,属性和方法都是定义在类的类体之中 。

类中的属性

属性:其实指的就是类中的成员变量(全局变量),是针对事物外部特征的描述;全局变量分为2类:a-----静态变量;b-----实例变量;
属性的定义语法
修饰符   [static]   数据类型  属性名称  [=];

属性的修饰符有哪些?

public :公共的;缺省 : 同一个包下可以进行访问;protected : 具有2层含义:a、同一个包下可以进行访问;b、具有继承关系的可以进行访问(不关系包的位置);private :只能在本类中进行使用,跨类则不能访问;----------------------------------------------------------static : 修饰属性表示这是一个静态的变量;final : 表示一个常量,必须要手动赋值;transient : 修饰属性防止属性被序列化(后续讲解);volatile : 属性同步的约定(涉及到Java多线程);
属性的访问

属性就是对象的外部特征的描述,我们在使用的过程中:

如果是静态的属性: 【类名.属性】名称 进行访问;

如果是实例的属性: 创建对象 , 再通过【对象.属性】进行访问;

类中的方法

方法:也称为“函数”,就是针对事物的功能进行的描述(表示能够干什么事情)。方法从静态性与否的角度进行分类:a、静态方法b、实例方法
方法的定义语法
修饰符   [static]   void|数据类型   方法名称(参数列表.....){//方法体;[return 值;]
}

方法的修饰符有哪些?

public :公共的;缺省 : 同一个包下可以进行访问;protected : 具有2层含义:a、同一个包下可以进行访问;b、具有继承关系的可以进行访问(不关系包的位置);private :只能在本类中进行使用,跨类则不能访问;-------------------------------------------------------------static : 修饰的方法为静态方法;final :修饰的方法为最终版本的方法,这种方法是不能被重写的;synchronized : 修饰的方法为线程同步(后续讲解);abstract : 抽象方法(抽象类的时候进行讲解);native : 本地方法(这种方法是没有方法体的,内部使用的是非Java语言实现的,更多的是CC++以文件的形式来实现的);
方法的调用

方法的分类(从静态与非静态的角度分): 静态方法 和 非静态方法;

静态方法:    【类名.方法名称】进行调用;实例方法:    创建对象,   再【对象.方法名称】进行调用;

方法的分类(有无返回值的角度分):有返回值 和 无返回值;

有返回值 :    数据类型  变量  =  调用方法();无返回值 :    调用方法();

方法的分类(有无参数列表角度分):有参数 和 无参数;

有参数的方法:    调用方法(实际值1,实际值2,....);无参数的方法:    调用方法();

区分静态和非静态

加载时机不同

  • 静态
    • 一个类中的静态成员会在类加载的时候,首先进行初始化(创建并产生默认值);
  • 非静态
    • 一个类中的实例成员会在创建类的对象的时候,才进行初始化;

生命周期不同

  • 静态
    • 静态的成员在类加载的时候创建,类被删除的时候销毁,声明周期较长;
  • 非静态
    • 实例成员在创建对象的时候初始化,对象销毁的时候一起销毁,相对较短;

共享性不同

  • 静态
    • 静态的成员是被这个类的对所有的对象共享的;
  • 非静态
    • 实例的成员是被每个对象独立的拥有;

访问方式不同

  • 静态
    • 静态的就是通过【类名.进行访问】;
  • 非静态
    • 实例成员必须要创建对象,再通过【对象.进行访问】;

过渡!

我们为何要使用Java作者开发出来的那些类?答:因为这些类中包含了我们所需要的一些功能,我们可以不用编写Java程序代码而直接使用。Java内部提供的所有的类,是不能完全满足我们的现实需求的,所以我们就需要自己定义出新的类。那么定义新的类的目
标是什么呢?答:如何使用这个类?需要创建类的对象来进行使用内部的属性和方法。结论:定义类不是目的,最终是为了使用类中的属性  和 方法。

对象的定义

对象的定义

class类是具有抽象性的,是对某一类事物的描述,它是一个基础也是一个前提条件,也可以把它视为一个“模板”。我们基于这个“模板”所产生出来的一个一个具体的东西,就称为“对象”。对象是客观存在的一个一个的个体,是看得见摸得着的客观事物。类:是抽象描述每一类事物------模板;对象:是类的具体化,客观存在的实体-----具体化;

类的具体化

针对已经存在的某个类,如何将其进行具体化呢?也就是如何创建出具体的对象呢?我们使用的是类中的【构造方法】来实现的;class类-------【构造方法】--------对象
什么是构造方法
构造方法也是属于方法,就是在类中使用类的名称作为方法的名称,并且永远都是如此。而且是没有所谓的返回值的约定(连void都没有),因为构造方法不做别的事情,就是生成对象的。
public  class  Student{//构造方法public  Student(){ }}
构造方法的特点

构造方法是特殊的方法,存在如下的几个特点:

1、构造方法的名称永远和类的名称是一致的;2、构造方法永远是没有返回值的约定的,连void都没有;3、一个类中可以同时存在多个构造方法,参数上会存在差别,不同的构造表达了不同的初始化程度;
public class Student {//属性public  String name;public  int   age;public  char  sex;//无参数的构造方法public  Student(){}//带有1个参数的构造方法public  Student(String name){//打印的name是局部变量中的name的值//局部变量和全局变量重名的时候,遵循的是就近原则//System.out.println(name); // “刘德华”  而不是 nullthis.name=name;//当成员变量和局部变量重名的时候,我们使用的是this关键字来进行区分的//this代表的是当前类(Student)的对象}//带有3个参数的构造方法public  Student(String name,int  age,char sex){this.name=name;this.age = age;this.sex = sex;}		
}Test.javapublic class Test {public static void main(String[] args) {/*//创建1个学生对象Student  stu1 = new  Student();//属性都是默认值System.out.println(stu1.name);//nullSystem.out.println(stu1.age);//0System.out.println(stu1.sex);//空白字符*//*Student   stu2 = new  Student("刘德华");*///使用同一个构造,创建多个对象Student   stu3 = new  Student("张学友",30,'男');System.out.println(stu3.name);System.out.println(stu3.age);System.out.println(stu3.sex);Student   stu4 = new  Student("张三丰",40,'男');System.out.println(stu4.name);System.out.println(stu4.age);System.out.println(stu4.sex);		}
}

说明!

1、调用构造创建对象的时候,使用的是new关键字;

2、选择使用不同的构造方法来创建对象,表达的是对当前这个对象不同程度的初始化;

4、我们调用构造方法的时候,使用的是 new 关键字;5、当我们的一个类中没有手动定义构造的时候,系统会默认一个不带参数的构造,一旦出现手动定义的构造,系统就不再默认了。6、一个类中同时存在的多个构造方法,就是构成了最为典型的“方法的重载”;   
方法的重载
  • 方法名相同;
  • 方法的参数不同(参数类型不同,参数的个数不同,参数的顺序不同):满足这三个条件至少一条即可认为参数的方法参数不同,
/*** MyBean类中定义几个方法来实现某些功能* * 演示方法的重载(MyBean类中的4个方法就构成了方法的重载)*/
public class MyBean{public double area(double a,double b){double c = a*b/2;System.out.println("三角形的面积"+c);return c;}public static void area(int a,int b){System.out.println("长方形的面积"+a*b);}public static double area(int r,double pi){double b = pi*r*r;System.out.println("圆的面积"+b);return b;}public static void area(int a,int b,int c){System.out.println("梯形的面积"+(a+b)*c/2);}
}public  class  DemoMathMain {public static void main(String[] args) {Student.area(16,18);double d = Math.PI;Student.area(9,d);Student.area(16,15,4);Student student = new Student();student.area(1.2,3.4);}
}
注意:
声明为final的方法不能被重载,声明为static的方法不能被重载,但能够再次声明
方法重载的优势
在功能确定的情况下,最大化满足外界灵活多变的需求。  比如:Arrays.sort(各种类型的数组);

附加内容:可变参数的使用

//任意的多个整数之和,咋办?---使用数组定义/** public int getSum(int[]  is){int sum = 0 ;if(is!=null&&is.length>0){for(int value:is){sum+=value;}}return sum;}*///使用可变参数来定义方法----可变参数public  int  getSum(int...  is){//在定义可变参数的时候,在参数列表中最多只能有1个,并且只能在列表的末端int sum = 0 ;if(is!=null&&is.length>0){for(int value:is){sum+=value;}}return sum;}

在方法进行调用的时候的差异对比:

        //首先需要将数据保存数组中int[]  is = {1,2,3,4,5,6};//才能使用这个方法来进行求和int sum = mb.getSum(is);	//使用可变参数后,的调用情况如下int sum = mb.getSum(1,2,3,4,5,6,7,8,9,10); //直接给出数据,不用在数组中进行封装,简单方	
构造方法的作用
1、基于类创建出对象;
2、基于创建的这个对象进行不同程度的初始化;

this关键字

this关键字永远表示的是 当前这个类的对象 的指代, 它是一个变量 ;
public class User {public  String  name;public  int   age;public   String  address;//自定义一个方法public  void   method1(){//通过user1.method1调用方法的时候,this指代的user1这个对象this.name = "admin";//通过user2.method1调用方法的时候,this指代的user2这个对象//总结://不管是user1 还是 user2对象,都是属于User这个类的对象;}...............
}	

UserTest.java

public class UserTest {public static void main(String[] args) {User user1 = new User();user1.method1();User user2 = new User();user2.method1();}
}

注意!

this关键字的使用场景:

1、用于在同一个类中进行重名的 局部变量 和 成员变量 的区分;

2、在同一个类中,this可以用于在【非静态的方法中】进行方法的互调;

​ 【this关键字是无法使用在静态的方法或者语句块中的】

3、在同一个类中,this可以进行构造的互调,并且只能是在第一行的位置;

类中的代码块

代码块:其实可以理解为一个没有名字的方法,也就是说属于“方法”的范畴。

在Java的类中,代码块可以分为2种形式:

  • 静态代码块

    • 为类中的静态成员做提前的准备和初始化工作
  • 实例代码块

    • 为类中的实例成员做提前的准备和初始化工作

package com.it.www.oop1;public class User {//main方法是程序执行的入口----JVM来控制的//在main方法执行之前需要有哪些动作?-----  类的加载的过程public static void main(String[] args) {new  User();}//静态代码块-------1、自动执行的      2、何时被自动执行的? (执行的比较早)static{System.out.println("----static-----");}//实例代码块-------1、自动执行   2、在创建User类的对象的时候执行的{System.out.println("----instance----");}}

提示!

不管是静态代码块还是实例代码块,都是属于方法。

完整的一个类的加载顺序

package com.it.www.oop1;public class User {private   static    int  age = 30;private    String   name = "name";public  User(){System.out.println("----User----");}//main方法是程序执行的入口----JVM来控制的//在main方法执行之前需要有哪些动作?-----  类的加载的过程public static void main(String[] args) {new  User();}//静态代码块-------1、自动执行的      2、何时被自动执行的static{System.out.println("----static-----");}//实例代码块-------1、自动执行   2、在创建User类的对象的时候执行的{System.out.println("----instance----");}}

总结:

1、在类被加载的过程中,所有的静态成员都被创建和初始化了。

2、在创建对象的过程中,才会针对所有的实例成员进行创建和初始化。

3、针对任意的成员变量,都会存在一个创建 (系统初始化值) + 初始化(手动赋值)。

继承关系

继承的基本概念

​ 继承是面向对象的三大特征之一,继承可以降低代码的冗余性,提高代码的效率,通过继承,子类获得父类的**成员变量,方法。**一个子类如何继承父类的字段和方法。

继承:是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例和方法,或子类从父类继承方法种,使得子类具有父类相同行为。

​ **继承的作用:**通过继承可以快速的创建一个类,实现代码的重用,提高程序的可维护性,节省大量时间,创建新类的时间,提高开发效率和开发质量,

​ 在Java种通过extends关键字可以申明一个类是从另外一个类继承而来的,

继承定义语法

继承机制的实现,就是在类的后面使用extends关键字来进行定义:public  class  Student   extends  Person{.......................
}public  class  Teacher  extends  Person{}Student类:是子类;Person类:是父类(基类);

注意!

在Java语言中【类与类之间】的继承,只能支持【单继承】。

继承案例

Person.java

package com.it.www.oop2;
/*** 父类(基类)----继承了Object类*/
public class Person {public  String  name;public  int   age;public  char  sex;public   void   sleep(){System.out.println("人睡觉!");}public   void   eat(){System.out.println("人吃饭!");}
}

Student.java

package com.it.www.oop2;
/*** 子类-----继承的是Person类*/
public class Student extends  Person{//通过继承来进行了替代/*public  String  name;public  int   age;public  char  sex;public   void   sleep(){System.out.println("人睡觉!");}public   void   eat(){System.out.println("人吃饭!");}*///以下的属于学生特有的属性 和 方法public  int  sNo;//学号public  void  study(){System.out.println("学生学习!");}
}

Student_Test.java

package test;import com.it.www.oop2.Student;public class Student_Test {public static void main(String[] args) {//创建一个学生对象Student  student = new  Student();//使用的是父类Person中继承过来的属性和方法student.name="小花";student.sex='女';student.age = 25;student.eat();student.sleep();//使用的是Student自身特有的属性和方法student.sNo = 1001;student.study();}
}

备注!

在继承的过程中,并不是将父类中所有的属性和方法都能同时继承过来,取决于各种不同的修饰符的规则。

在继承的使用中,可以适当的使用不同的修饰符针对属性和方法进行保留。

在使用继承的过程中,需要注意的事项:

1、extends的实现,一定是依赖父子之间的构造方法的。2、子类的构造中通过super来调用了父类中相应的构造方法来进行初始化(不能不对应,否则继承不成立)。3、super就是用于在子类的构造中调用父类的构造,只能在是子类的构造方法的第一行,所以和this实现构造互调的时候,不能搭配使用。

super关键字

super关键字的使用场景
1、用于父子之间的构造方法中,实现构造的调用。2、在父子类之间可以通过super来区分重名的属性 和 方法。3、语法特点:super只能是使用在非静态的方法或者语句块中。4、super关键字必须要写

方法的重写

方法重写的定义
  • 继承关系中(方法名相同,参数列表相同,返回数据类型)称为“方法的重写”

  • 方法的重写也讲为:“方法的覆写”、“方法的改写”。

方法重写案例

Demo.java(父类)

public class Demo {int age ;String name ;String sex;void  test(){System.out.println("张三");System.out.println("18");System.out.println("nan");}
}

DemoSon.java(子类)

public class DemeSon extends Demo{void  test(){super.age=89;super.name = "张三";super.sex="男";super.test();}}

Demo1.java(测试类)

public class Demo1{public static void main(String[] args) {DemoSon1 demeSon = new DemoSon1();demeSon.test();}}

附加知识点!

User.java

package com.it.www.bean;public class User {public  String name;public   int  age;public User() {super();}public User(String name, int age) {super();this.name = name;this.age = age;}//重写了Object类中的toString方法public String toString() {return "User [name=" + name + ", age=" + age + "]";}}

UserTest.java

package test;import com.it.www.bean.User;public class UserTest {public static void main(String[] args) {User user = new User("admin",30);//打印输出(地址)----默认的调用的是toString方法System.out.println(user); //com.it.www.bean.User@15db9742//重写toString方法后的结果:User [name=admin, age=30]				}	
}

需求:

User 对象 user1===== [name=“admin”,age=30]

User对象 user2===== [name=“admin”,age=30]

user1 和 user2 是两个不同的对象,但是数据信息又是相同的。我们想比较出2个对象中的数据是否相同?答:重写类中的equals方法,实现的是内容信息的比较即可。//重写父类的equals方法-----实现内容信息的比较
public boolean equals(Object obj) {if(this==obj){return true;}if(obj instanceof User){User user = (User)obj;//this.name中的equals方法,就是String类中的equals方法,作者已经重写过了,实现的内容的比较if(this.name.equals(user.name)&&this.age==user.age){return true;}}return false;}

注意!

Object 类中的equals方法实现的是对象的地址的比较。

String类中的equals方法已经重写过了,实现的是内容信息的比较。

将来自定义的类中的equals方法比较的是什么?取决于自己是否进行重写。

重写和重载的区别
重写是发生在继承关系中的,方法名相同,参数列表相同,返回数据类型形同同一个类中,方法名相同参数不同(数量不同,顺序不同,数据类型不同)
总结
  • 父类中的属性定义为私有,子类不能继承其父类中的private成员,如果我们子类想要访问父类成员可以写为public和不写,protected,
  • 子类继承父类之后,其成员修饰符必须大于或者等于父类中的修饰符,不可将其降低修饰符的访问权限,
  • 方法的重写一定是在父子类继承关系中产生的
  • 子类无法访问父类中的静态(static)成员
  • 子类重写父类中的方法,(方法名必须和父类中的相同,方法中的参数一致,返回的数据类型一致)
  • super关键字:可以在子类中通过super来调用父类中的被重写的方法和访问父类中成员;

多态

概念

​ 多态是面向对象中最重要的特征之一,指同一个事物在不同场景下有着不同的形式。同一个对象在不同时刻,代表的对象不一样,指的是对象的多种形态

​ 可以把不同的子类对象都当作父类来看,进而屏蔽不同子类对象之间的差异,写出通用的代码,做出通用的编程,统一调用标准。

特点

  • 多态的前提是:
    • 继承
    • 要有方法的重写
  • 父类引用指向子类对象:Demo demo = new DemoSon();
  • 多态中,编译看左边,运行看右边。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RoeLvEPj-1677669224022)(面向对象.assets/image-20220808150342073.png)]

多态案例

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zKUoyW0A-1677669224024)(面向对象.assets/image-20221026101303918.png)]

父类

/*** 多态的前提是:继承+重写* 创建父类*/
public class Demo {public void eat(){System.out.println("水");}
}

子类1

/*** 创建子类*/
public class DemoExtendsSon1 extends Demo{//重写父类中的eat方法public void eat() {System.out.println("0°一下----");}//延展子类中的方法public void jump(){System.out.println("冰");}
}

子类2

public class DemoExtendsSon2 extends Demo{//添加父类中的方法,进行重写public void eat() {System.out.println("0°以上------");}//延展子类方法,public  void run(){System.out.println("水");}
}

子类3

public class DemoExtendsSon3 extends Demo{//重写父类中的方法public void eat() {System.out.println("100°以上--------");}//子类方法延展public void du(){System.out.println("气");}
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jhjHTXTO-1677669224024)(面向对象.assets/image-20220808152501438.png)]

getter,setter方法

package com.sin.demoExtends;public class DemoCar {//汽车品牌private String name;private    String color="五彩斑斓的黑";//汽车颜色private double money;//价格private int id;//汽车idpublic void start(){System.out.println("父类--这个车可以开"+color);}public void stop(){System.out.println("父类--这个车可以停");}public String getName(){//获取汽车名称System.out.println(name);return name;//返回汽车名称}public void setName(String name){//设置汽车名称this.name = name;//将参数name赋值给属性}public String getColor(){//获取汽车颜色System.out.println(color);return color;}public void setColor(String color){//this.color=color;}public double getMoney() {return money;}public void setMoney(double money) {this.money = money;}public int getId() {return id;}public void setId(int id) {this.id = id;}}

子类1

package com.sin.demoExtends;public class DemoCarExtendsSon1 extends DemoCar{//重写父类方法public void start() {System.out.println("这个开的很快");}}

子类2

package com.sin.demoExtends;public class DemoCarExtendsSon2 extends  DemoCar{//重写父类方法public void stop() {System.out.println("这个车刹车灵");}//延展子类方法public void swim(){System.out.println("他的安全性高,有安全带");}
}

测试

public class TestDemoCar {public static void main(String[] args) {//实例化子类DemoCarExtendsSon1 demoCarExtendsSon1 = new DemoCarExtendsSon1();demoCarExtendsSon1.setName("劳斯莱斯");demoCarExtendsSon1.getName();demoCarExtendsSon1.setColor("黑色");demoCarExtendsSon1.getColor();demoCarExtendsSon1.setId(12138);System.out.println(demoCarExtendsSon1.getId());demoCarExtendsSon1.setMoney(10000000.23);System.out.println(demoCarExtendsSon1.getMoney());demoCarExtendsSon1.start();DemoCarExtendsSon2 demoCarExtendsSon2 = new DemoCarExtendsSon2();demoCarExtendsSon2.stop();demoCarExtendsSon2.swim();}
}

多态的好处

1,多态可以让我们不同关心某个对象到底具体是什么类型,就可以使用该对象的某些方法

2,提高了程序的可扩展性,可维护性

多态的使用

前提:多态的对象是将自己看作父类类型

  • 成员变量:使用的是父类的
  • 成员的方法:由于存在重写现象,所以使用的是子类的
  • 静态的成员:随着子类调用父类加载而加载

抽象类

抽象类的基本概述

​ 普通类是一个完善的功能类,可以直接产生实例对象,并且普通类中有构造方法,普通方法,static方法,变量和常量等,而抽象类是指在普通类的结构里面增加了抽象方法的组成部分

​ 抽象类是无法实例化的,

​ 什么叫抽象方法:在所有的普通方法上面都会有“{}”,这表示方法体,有方法体的方法一定可以被对象直接调用,而抽象方法,是指没有方法体的方法 ,同时抽象方法还必须使用关键字abstract关键字来申明

​ 拥有抽象方法的类就是抽象类,抽象类要使用abstract关键字声明;

抽象类的使用

抽象方法的语法格式:

修饰符   abstract   void/数据类型   方法名称(参数列表...);
抽象的方法(父类)
/*** 抽象类* 1,可以写普通方法,* 2,可以写抽象方法* 3,可以写变量* 4,可以写常量* 5,不可以写静态抽象方法,* 6,可以写构造方法*7,可以写静态方法*/
public abstract class DemoAbstatis01 {public void test(){System.out.println("helloword");}public abstract void test1();/*** 抽象方法,计算圆周长*/public abstract  void getPerimeter();/*** 抽象方法,* 获取圆的面积*/public abstract void getArea();}
继承抽象方法的子类
public class DemoAbstractSon1 extends DemoAbstatis01{@Overridepublic void test1() {System.out.println("我继承了我爸爸的抽象方法");}/*** 抽象的父类方法中强制实现的方法* 计算周长*/@Overridepublic void getPerimeter() {double r = 2.0;System.out.println("圆的周长"+Math.PI*2*r);}/*** 抽象的父类方法中强制实现的方法* 计算圆的面积*/@Overridepublic void getArea() {double r = 19.28;System.out.println("圆的面积"+Math.PI*r*r);}
}
测试类
public class DemoMain {public static void main(String[] args) {DemoAbstractSon1 demoAbstractSon1 = new DemoAbstractSon1();demoAbstractSon1.test1();demoAbstractSon1.test();demoAbstractSon1.getPerimeter();demoAbstractSon1.getArea();}
}
抽象类的使用原则:
  • 抽象类的修饰符,必须为public/protected,也可以不用写默认为public,不能写为private
  • 抽象类不能被直接实例化,可以通过子类采用向上转型的方式进行实例化,(使用父类实例化子类)
  • 抽象类必须有子类,可以有多个子类继承,使用extends继承,一个子类只能继承一个父类。
  • 子类在继承抽象父类的时候必须覆写抽象父类中的抽象方法,(如果不覆写父类中的抽象方法,则将类写为抽象类)
  • 子类继承抽象父类的时候,抽象方法必须被覆写,普通方法可以选择性覆写。
向上转型
//抽象类---------------------------------------------------------------
/*** 自定义的抽象类*/
public abstract class A {public void test(){//普通方法System.out.println("这是抽象类中的普通方法");}public abstract void test1();
}
//子类继承抽象父类---------------------------------------------------------------
/*** B类是抽象类的子类,是一个普通类*/
public class B extends A{@Overridepublic void test1() {System.out.println("helloword");}
}
//测试类---------------------------------------------------------------
public class DemoMain {public static void main(String[] args) {//向上转型(父类实例化子类)A c = new B();c.test();c.test1();}
}
  • 抽象类也是一种复合引用类型。

  • 类 可以继承 类

  • 抽象类 可以继承 类

  • 类 可以继承 抽象类

  • 抽象类 可以继承 抽象类

练习

父类
public  abstract class DemoAbstract02 {/*** 长方形面积* @param a 长* @param b 宽* @return 长方形面积a*b*/public abstract double area(double a,double b);/*** 三角形面积* @param a 底* @param b 高* @return 面积 a*b/2*/public  abstract  double area(double a,int b);/*** 梯形面积* @param a 上底* @param b 下底* @param c 高* @return 体形面积 (a+b)*c/2*/public abstract  double area (double a,double b , double c);/*** 三角形周长* @param a 边长* @param b 边长* @param c 边长* @return 三角形走场:a+b+c*/public abstract double perimeter(double a,double b,double c);/*** 长方形周长* @param a 长* @param b 宽* @return (a+b)*2*/public abstract double perimeter( double a, double b);/*** 正方形* @param a 边长* @return a*4*/public abstract double perimeter( double a);}
子类
public class DemoAbstractSon2 extends DemoAbstract02{/*** 长方形面积* @param a 长* @param b 宽* @return*/@Overridepublic double area(double a, double b) {double c=a*b;return c;}/*** 三角形面积* @param a 底* @param b 高* @return*/@Overridepublic double area(double a, int b) {double c= a*b/2;return c;}/*** 梯形面积* @param a 上底* @param b 下底* @param c 高* @return*/@Overridepublic double area(double a, double b, double c) {double e = (a+b)*c/2;return e;}/*** 三角形周长* @param a 边长* @param b 边长* @param c 边长* @return*/@Overridepublic double perimeter(double a, double b, double c) {double d = a+b+c;if (a==b && b==c){System.out.println("是等边三角形");}else if (a==b || a==c || c==b){System.out.println("这是等腰三角形");}return d;}/*** 长方形周长* @param a 长* @param b 宽* @return*/@Overridepublic double perimeter(double a, double b) {double c = (a+b)*2;return c;}/*** 正方形周长* @param a 边长* @return*/@Overridepublic double perimeter(double a) {double c = a*4;return c;}
}
测试类
public class DemoMain {public static void main(String[] args) {DemoAbstract02 demo = new DemoAbstractSon2();double c = demo.area(12.3,36.5);System.out.println("长方形面积"+c+"cm²");System.out.println("三角形面积"+demo.area(6.3,3)+"cm²");double a = demo.area(3.3,6.6,9.9);System.out.println("梯形面积"+a+"cm²");System.out.println("------------------------------------------------------------------");double a1 = demo.perimeter(9.9);System.out.println("正方形周长"+a1);}
}

接口

接口基本概念

​ 官方解释:Java接口就是以系列方法的声明,

​ 接口可以理解为特殊的类,里面全是全局变量公开的抽象方法,所组成,接口解决的问题Java无法使用多继承的一种手段。一个接口只有方法的特征没有方法的具体实现。或者我们可以直接把接口理解为全部都为抽象类,接口中必须都为抽象方法。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-p39Hmeuu-1677669224025)(面向对象.assets/image-20220810141526292.png)]

接口的特点

  • 接口中全是抽象方法,全局变量
  • 接口指明了一个类必须要做什么,和不能做什么,

接口的定义语法

public|缺省   interface    接口名称{//定义常量: //public  static  final  数据类型   常量名称 = 值;//抽象方法://public  abstract  void/数据类型   方法名称(参数列表...);
}

注意!

接口是没有构造方法的,更不能创建对象。只是定义一种规则和规范。

package com.it.www.oop1;
/*** 介绍接口的语法格式* @author Administrator**/
public interface InterfaceA {public static final  String  NAME="admin";//在接口中定义常量的格式为:public static final//如果我们在定义的时候存在相应的省略,默认的也是 public static finalpublic static   String  NAME1="admin";public    String  NAME2="admin";//所以我们通常在开发的过程中,为了相应的简化写法,一般是这样做的。String  NAME3="admin";//抽象方法:默认的修饰符是 public   abstract public  abstract  void   method1(String name);//通常在开发中为了简化,可以这样写:void  method2(String name);	
}

接口使用

InterfaceB.java

package com.it.www.oop1;public interface InterfaceB {//分页单位为 5int  PAGE_SIZE = 5;int   getPageSize();int   getPageData();}

MyClass.java 实现类

package com.it.www.oop1;/*** MyClass是一个类,这是实现InterfaceB这个接口的一个实现类。* @author Administrator*/
public class MyClass implements InterfaceB {public int getPageSize() {//可以使用 this.PAGE_SIZE来进行使用,说明PAGE_SIZE已经是MyClass类中的常量了,所以,接口有这么一个规定//只要是这个接口的实现类,都可以毫无条件的共享接口中的全部常量。return this.PAGE_SIZE;}public int getPageData() {return 0;}}

注意!

1、定义接口使用的是interface关键字;

2、接口中只有常量和抽象方法2部分;

3、实现类来实现接口使用的是implements关键字;

4、实现类一旦实现了某个接口,就可以毫无条件的共享接口中的所有常量;

InterfaceC.java

package com.it.www.oop1;public interface InterfaceC {String  NAME = "刘德华";String   getName();int    getAge();}

MyClass.java

package com.it.www.oop1;/*** MyClass是一个类,这是实现InterfaceB这个接口的一个实现类。* @author Administrator*/
public class MyClass implements InterfaceB , InterfaceC{public int getPageSize() {//可以使用 this.PAGE_SIZE来进行使用,说明PAGE_SIZE已经是MyClass类中的常量了,所以,接口有这么一个规定//只要是这个接口的实现类,都可以毫无条件的共享接口中的全部常量。return this.PAGE_SIZE;}public int getPageData() {return 100;}public String getName() {return this.NAME;}public int getAge() {return 30;}
}

提示!

同一个类可以同时实现多个接口,多个接口之间使用【,】号进行分隔;

InterfaceD.java

package com.it.www.oop1;
/*** 接口之间也是可以继承的,并且可以支持多重继承。* @author Administrator*/
public interface InterfaceD  extends InterfaceB,InterfaceC {void   method01();void   method02();}

MyClass1.java

package com.it.www.oop1;/*** 实现类中需要实现的方法就包含了IntefaceB 、 C 、 D中的所有的抽象方法 和 共享了所有的接口中的所有常量* @author Administrator*/
public class MyClass1 implements InterfaceD {public int getPageSize() {// TODO Auto-generated method stubreturn 0;}public int getPageData() {// TODO Auto-generated method stubreturn 0;}public String getName() {// TODO Auto-generated method stubreturn null;}public int getAge() {// TODO Auto-generated method stubreturn 0;}public void method01() {// TODO Auto-generated method stub}public void method02() {// TODO Auto-generated method stub}
}

提示!

1、接口之间是可以继承的,并且可以支持多重继承;

2、独立的接口就是某一类独立的操作,不同的接口可以同时作用(implements)在需要的类上;

3、弥补了Java中类只支持单继承的局限性;

上机任务

任务1:

编写一个接口:描述USB的功能。service 方法;
实现类1:U盘。连接接口,实现数据的传输
实现类2:USB电风扇。连接接口,接通电源,启动风扇
/*** usb的服务*/
public interface USBService {public void useTxt();}/*** 实现类1,*/
public class USBServiceImpl implements USBService{@Overridepublic void useTxt() {System.out.println("连接接口,实现数据的传输");}
}/*** 实现类2*/
public class USBServiceImpl2 implements USBService {@Overridepublic void useTxt() {System.out.println("连接接口,接通电源,启动风扇");}
}/**
* 测试类
*/
public class TestMain {public static void main(String[] args) {USBServiceImpl service = new USBServiceImpl();service.useTxt();USBServiceImpl2 service1 = new USBServiceImpl2();service1.useTxt();}
}方法2-------------------------------------------------------------------/*** usb的服务*/
public interface USBService {/*** 常量,功能1*/public  final String U_DISK = "连接接口,实现数据的传输";/*** 常量,功能2*/public final  String ELECTRIC_FAN="连接接口,接通电源,启动风扇";/*** 描述usb的功能*/public void useTxt();}
/*** 实现类1,*/
public class USBServiceImpl implements USBService{@Overridepublic void useTxt() {System.out.println(U_DISK);}}
/*** 实现类2*/
public class USBServiceImpl2 implements USBService {@Overridepublic void useTxt() {System.out.println(ELECTRIC_FAN);}
}

任务2:

实现一个防盗门的功能:门: 开门 、 关门的功能;锁: 开锁 、关锁的功能;防盗门  ---- 是门 ----- 锁请问如何进行设计?附加一个门铃(响,咔嚓拍照,进行存储)如何进行设计?

接口的特点

1、定义的时候使用的是interface关键字;2、接口就是用于负责定义功能(规范 或 标准);3、接口中是没有构造方法的;4、接口都是通过实现类使用implements 来进行实现的;5、接口中只有常量 和  抽象方法;6、接口之间是可以进行继承的,并且可以支持多重继承;7、接口重点在于一种设计中的使用(主要是针对模块 、 系统)之间来进行衔接的;

抽象类和接口的区别

抽象类与接口在语法上的区别1.抽象类里可以有构造方法,而接口内不能有构造方法。
2.抽象类中可以有普通成员变量,而接口中不能有普通成员变量。
3.抽象类中可以包含非抽象的普通方法,而接口中所有的方法必须是抽象的,不能有非抽象的普通方法。
4.抽象类中的抽象方法的访问类型可以是public ,protected和默认类型,但接口中的抽象方法只能是public类型的,并且默认即为public abstract类型。
5.抽象类中可以包含静态方法,接口内不能包含静态方法。
6.抽象类和接口中都可以包含静态成员,抽象类中的静态成员变量的访问类型可以任意,但接口中定义的变量只能是public  static  final类型,并且默认为public  static  final类型。
7.一个类可以实现多个接口,但只能继承一个抽象类。
8.抽象类和接口所反映出的设计理念不同。其实abstract class表示的是“is-a”继承关系,interface表示的是“like-a”关系。两者在应用上的区别接口更多的是在系统框架设计方法发挥作用,主要定义模块或者系统之间的通信,而抽象类主要在代码实现方面发挥作用,可以实现代码的重用。

面向接口编程模式

com.it.www.dao : 定义数据库操作的接口包;

com.it.www.daoi : 定义数据库操作的接口的实现包;

com.it.www.service : 定义项目业务操作的接口包;

com.it.www.servicei : 定义业务操作的实现包;

PersonDao.java 接口

package com.it.www.system;public interface PersonDao {void  savePerson();void  queryPersons();}

PersonDaoImple.java实现类

package com.it.www.system;public class PersonDaoImple implements PersonDao {//实现的是接口中的方法public void savePerson() {System.out.println("---save Person----");}public void queryPersons() {System.out.println("----query  persons----");}//自己这个类的方法public  void   myMthod01(){System.out.println("----customer 1-----");}public  void   myMthod02(){System.out.println("----customer 2-----");}}

Test.java

package com.it.www.system;public class Test {public static void main(String[] args) {//使用 实现类的类型  创建  实现类的对象PersonDaoImple   personDaoImple = new  PersonDaoImple();personDaoImple.savePerson();personDaoImple.queryPersons();personDaoImple.myMthod01();personDaoImple.myMthod02();//使用面向接口编程模式//使用接口的类型  接收  实现类的对象PersonDao    personDao = new  PersonDaoImple();//是PersonDao的类型,就只能调用出PersonDao中定义过的方法。personDao.queryPersons();personDao.savePerson();//实现类PersonDaoImple中的自己的方法丢了。被接口给过滤了,所以,接口永远对外提供的功能都只是接口中定义过的功能。}}

提示!

更多的基于接口的分层结构和面向接口的编程模式,见: day05_09 项目中;

封装

  • 封装:(数据的隐藏),通常,应该禁止直接方法一个对象中的数据,而是通过操作接口来访问,成为信息隐藏
public class User {//名字private String name;//性别private String sax;//年龄private int age;public User(){}public User(String name,String sax,int age){this.name = name;this.sax = sax;this.age = age;}public void test(String name, String sax, int age){this.name=name;System.out.println(name);this.sax = sax;System.out.println(sax);this.age = age;System.out.println(age);}public String getName() {//获取对象数据return name;}public void setName(String name) {//设置对象数据this.name = name;}public String getSax() {return sax;}public void setSax(String sax) {this.sax = sax;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}
}
package com.sin.pojo;public class UserMain {public static void main(String[] args) {User user = new User();user.setName("张三");user.setAge(18);user.setSax("男");System.out.println(user.getName());System.out.println(user.getAge());System.out.println(user.getSax());User user1 = new User("李四","女",29);System.out.println();System.out.println(user1.getSax());System.out.println(user1.getName());System.out.println(user.getAge());user.test("王五","男",89);}
}

当一个类中的变量别private(私有)只能在当前类下访问,他无法在主程序中直接调用,需要其他的一些方法调用

怎么对类中私有的变量进行操作?

  • get : 获取对象中的值
  • set : 设置对象的值
  • 构造方法,普通方法,

为什么封装

  • 提高程序的安全性,保护数据
  • 隐藏代码的实现细节
  • 统一接口
  • 提高系统的可维护性

内部类

内部类的基本知识

内部类:就是定义在一个类的内部的类。内部类就是专门负责独立的描述某一类事物,而这一类事物仅仅只是在当前这个所在类的范围内进行使用。在类中的任意位置需要提供局部性的服务,就可以使用内部类来实现。问题1:可以定义在一个指定的类内部的哪些位置?答:任意位置(直接在类体中、方法中、代码块中、语句块中)。问题2:为什么要使用内部类?答:就是为了在一个类的内部的任意的位置提供局部性的服务。

内部类

  • 成员内部类
  • 局域内部类
  • 匿名内部类
  • 静态内部类
成员内部类

成员内部类,是最普通的内部类,它的定义为位于另一个类的内部,

public class Demo {public static void main(String[] args) {Demo demoA = new Demo();Demo.DemoA demoA1 = demoA.new DemoA();}public class  DemoA{public DemoA(){System.out.println("我是内部类");}}
}
局域内部类

局部内部类使用比较少,其声明在一个方法体中,在局部内部类里面可以访问外部类中的对象的所有访问权限的字段,而外部类不能访问局部内部类的中定义的字段

public class Demo {private String name1 = "zhangsan";public static void main(String[] args) {Demo demo  = new Demo();demo.test1();}public void test1(){//局部类,-->基于普通方法之的classclass A{private String name;public A(){//A类的无参构造方法System.out.println(name1);System.out.println("我是局部变量");}public String getName() {return name;}public void setName(String name) {this.name = name;}}//创建对象的目的是:让Java虚拟机识别到A类的对象A a = new A();a.setName("王五");System.out.println(a.getName());}}
匿名内部类

匿名内部类有很多种形式,其中最常见的一种形式为方法参数中新建一个接口对象/类对象,并且实现这个接口声明,类中原有的方法:

接口匿名内部类
public class Demo {public static void main(String[] args) {Demo demo = new Demo();demo.DemoTest();}//自定义接口public interface Test{//抽象方法public void test1();public String testName(String name);}private void DemoTest() {//在这个过程中会创建一个匿名内部类对象//这个匿名内部类实现Test接口中方法并重写test1Test test = new Test(){String name;@Overridepublic void test1() {System.out.println("我是匿名内部类");}@Overridepublic String testName(String name) {this.name=name;return name;}};//对象调取方法test.test1();System.out.println(test.testName("我在测试匿名内部类"));}}
抽象匿名内部类
public class Demo {public static void main(String[] args) {Demo demo = new Demo();demo.test1();}//自定义抽象类public abstract class Test{//抽象方法public abstract  String test(String name);public void test1(){System.out.println("这是匿名内部类中的普通方法");}}public void test1(){Test test = new Test(){String name;@Overridepublic String test(String name) {this.name = name;return name;}};test.test1();System.out.println(test.test("这是抽象类的匿名内部类"));System.out.println("_______________");}
}

在方法中new一个接口/抽象类,并实现接口/抽象类中的抽象方法,在这过程中其实会创建一个匿名内部类实现这个接口/抽象类,并重写接口/抽象类中的方法。

静态内部类

一个类的静态成员独立于这个类的任何一个对象存在,只要在具有访问权限的地方,我们就直接可以类.方法名的形式来访问这个静态成员。静态内部类也可以作为外部类的静态成员而存在,创建一个类的静态内部类对象不需要依赖外部类对象,可以直接类名.方法名

public class Demo {public static void main(String[] args) {Demo1.test();}//自定义静态内部类static class Demo1{public Demo1(){}public static void test(){String name = "这是";String name1 = "静态";String name2 = "内部类";System.out.println(name+name1+name2);}}
}

上机任务:

以上我们使用针对User对象数组进行了自定义的排序处理,使用的是Comparetor接口,其实还存在另一个比较器的接口,同样可以实现在Arrays.sort中进行排序处理(自己查阅一下完成)。

标准JavaBean规范

JavaBean的定义:就是一个class类。标准的JavaBean的定义:其实就是在JavaBean的基础上设置了一些规则和规范。1、所有的属性都是private修饰的;2、所有的属性的名称的首字母一定是小写的;3、所有的属性都会对应一个公共的set(赋值) 和  get(取值)方法;4、一般会添加上一个无参数的构造和一个全部带参数的构造;

注意!

以后我们会学习到Java的反射机制,反射机制中都会遵循标准JavaBean的规范来进行处理。

package com.it.www.entity;public class User {private   String  name;private   String  address;private   int   age;private    char  sex;public User() {super();}public User(String name, String address, int age, char sex) {super();this.name = name;this.address = address;this.age = age;this.sex = sex;}//get方法是有返回值的,返回类型就是属性的类型,是没有参数的//get+属性名称的首字母大写+后面的所有的字符保持不变public String getName() {return name;}//属性:  Name//set方法名称:  setName//根据set方法名称还原属性名称//Name------name//set方法是赋值的,参数的类型就是属性的类型,是没有返回值的public void setName(String name) {this.name = name;}public String getAddress() {return address;}public void setAddress(String address) {this.address = address;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public char getSex() {return sex;}public void setSex(char sex) {this.sex = sex;}}
http://www.xdnf.cn/news/11113.html

相关文章:

  • HTML代码实例:详细讲解超级链接--网页制作
  • 07-SNAP处理Sentinel-1 IW GRD数据
  • Java:设计模式之结构型-装饰者模式(decorator pattern)
  • 获取加载后就自动删除的驱动SYS文件
  • 聚合命令
  • 勒索病毒的策略与建议
  • psp记忆棒测试软件,PSP记忆棒有问题?修复软件MS-Format帮你解忧
  • 最新传奇木马及其防范全攻略
  • 经典网页设计:25个优秀的个人网站设计欣赏
  • 另类的中文乱码
  • Webmax简易入门操作手册(一)
  • QQ在线聊天代码
  • 代理商丨UltraEdit是一套功能强大的文本编辑器
  • 小知识·BitTorrent 简介
  • SELinux入门:了解和配置SELinux
  • .NET下的内存分配机制
  • oracle10g oui-10118,使用ORACLESTREAMSTRMMON监控工具
  • 硬件和软件的关系
  • 51 地图基本接口(三)
  • JS中设置按钮不可用的disabled属性
  • 对战平台原理分析
  • Java中的二进制及基本的位运算
  • 基于51单片机的电子秤设计
  • 基于wifi的室内定位算法设计与实现
  • 2023-2025 时序大模型相关工作汇总
  • 《MyEclipse v8.0M1 绿色注册版》(MyEclipse Enterprise Workbench v8.0M1)8.0M1[压缩包]
  • iOS之JavaScript与OC的相互调用:WKwebview 的使用
  • 【转】3DSMax各个版本的下载地址
  • win7 蓝屏 0x000000c5
  • 提供开放平台网站列表- OpenAPI