java面向对象
2021/7/26 11:05:53
本文主要是介绍java面向对象,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
面向对象
- 面向对象编程(Object-Oriented Programming,OOP)
- 面向对象编程的本质是:以类的方式组织代码,以对象的组织(封装)数据。
什么是面向对象
面向对象的方法主要是把事物给对象化,包括其属性和行为。面向对象编程更贴近实际生活的思想。总体来说面向对象的底层还是面向过程,面向过程抽象成类,然后封装,方便使用就是面向对象(万物皆对象)。
面向对象和面向过程的区别
面向过程就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用就可以了;面向对象是把构成问题事务分解成各个对象,建立对象的目的不是为了完成一个步骤,而是为了描叙某个事物在整个解决问题的步骤中的行为。
创建和初始化对象
- 使用new关键字创建对象时,除了分配内存空间外,还会给创建好的对象进行默认的初始化,以及对类中构造器的调用
- Student.java
package com.kuangshen.OOP; public class Student { String name; int age; public void study() { System.out.println(this.name + "在学习" + " 他已经" + this.age + "岁了"); } }
- Application.java:
package com.kuangshen.OOP; public class Application { public static void main(String args[]) { Student student1 = new Student(); Student student2 = new Student(); student1.name = "小明"; student1.age = 12; student2.name = "小红"; student2.age = 11; System.out.println(student1.name + " " + student1.age); } }
-
类中的构造器也称为构造方法,是在进行创建对象的时候必须调用的。并且构造器有以下两个特点:
- 必须和类的名字相同
- 必须没有返回类型,也不能写void
-
其作用如下:
- 利用new调用构造器
- 初始化对象的值
-
案例如下:
-
Person.java
-
package com.kuangshen.OOP; public class Person { //一个类即使什么都不写也会有一个默认构造器方法。与类名相同并且没有返回值 String name; int age; public Person() { this.name= "神州";//可以什么都不写 } public Person(String name) { this.name = name; } public Person(int age, String name) { this.age = age; this.name = name; } }
-
Application.java
-
package com.kuangshen.OOP; public class Application { public static void main(String args[]) { Person person = new Person(); System.out.println(person.name); } }
-
-
注意:定义有参构造之后,如果想要使用无参构造,我们需要显示的定义一个无参构造(在一般条件下,无参构造不用写,系统也会默认自带一个)。
-
下面例子会报错,需要把Person.java中的无参构造的注释去掉:
-
package com.kuangshen.OOP; public class Person { //一个类即使什么都不写也会有一个默认构造器方法。与类名相同并且没有返回值 String name; int age; /*public Person() { this.name= "神州";//可以什么都不写 }*/ public Person(String name) { this.name = name; } }
package com.kuangshen.OOP; public class Application { public static void main(String args[]) { Person person = new Person(); System.out.println(person.name); } }
-
封装
-
该露的露,该藏的藏
- 我们程序设计要追去高内聚,低耦合。高内聚就是类的内部数据操作细节自己完成,不允许外部干涉;低耦合就是仅暴露少量的方法给外部使用。
-
封装:数据的隐藏
- 通常,应禁止直接访问一个对象中数据的直接表示,而应通过操作接口来访问,这称为信息隐藏。
-
封装中提出了private关键字,利用这个关键字,可以避免对数据的直接表示,代码如下:
-
ackage com.kuangshen.OOP; public class Teacher { private int age; private String name; public void setName(String name) { this.name = name; } public String getName() { return this.name; } }
-
package com.kuangshen.OOP; public class Application { public static void main(String args[]) { Teacher teacher = new Teacher(); teacher.setName("天才"); System.out.println(teacher.getName()); // System.out.println(teacher.name);//不可以对数据直接操作 } }
-
继承
-
继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为。
-
继承一般使用extend关键字,其中people.java,people1.java和Application.java的例子如下:
-
package com.kuangshen.OOP; public class people { private int age; public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
-
package com.kuangshen.OOP; public class people1 extends people{ public void say() { System.out.println(getAge()); } }
-
package com.kuangshen.OOP; public class Application { public static void main(String args[]) { people1 person = new people1(); person.setAge(5); person.say(); } }
-
-
继承类型
- 需要注意的是 Java 不支持多继承,但支持多重继承。
-
继承的特性
- 子类拥有父类非 private 的属性、方法。
- 子类可以拥有自己的属性和方法,即子类可以对父类进行扩展。
- 子类可以用自己的方式实现父类的方法。
- Java 的继承是单继承,但是可以多重继承,单继承就是一个子类只能继承一个父类,多重继承就是,例如 B 类继承 A 类,C 类继承 B 类,所以按照关系就是 B 类是 C 类的父类,A 类是 B 类的父类,这是 Java 继承区别于 C++ 继承的一个特性。
- 提高了类之间的耦合性(继承的缺点,耦合度高就会造成代码之间的联系越紧密,代码独立性越差)。
-
继承关键字
- 继承可以使用 extends 和 implements 这两个关键字来实现继承,而且所有的类都是继承于 java.lang.Object,当一个类没有继承的两个关键字,则默认继承object(这个类在 java.lang 包中,所以不需要 import)祖先类。
-
super关键字
-
super关键字:我们可以通过super关键字来实现对父类成员的访问,用来引用当前对象的父类。
this关键字:指向自己的引用。
后面people.java,people1.java和Application.java的例子如下:
package com.kuangshen.OOP; public class people { protected String name = "天下"; public void print() { System.out.println("1"); } }
package com.kuangshen.OOP; public class people1 extends people{ private String name = "月关"; public void print() { System.out.println("2"); } public void test(String name) { System.out.println(name); System.out.println(this.name); System.out.println(super.name); } public void test1() { print(); this.print(); super.print(); } }
package com.kuangshen.OOP; public class Application { public static void main(String args[]) { people1 person = new people1(); person.test("天马"); person.test1(); } }
最终的结果如下:
天马 月关 天下 2 2 1
-
-
super构造器
-
super无参构造器
package com.kuangshen.OOP; public class people1 extends people{ public people1() { //隐藏代码,调用了父类的构造器 super();//可加可不加,但是加了必须在第一行。 System.out.println("使用了子类构造器"); } }
package com.kuangshen.OOP; public class people { public people() { System.out.println("使用了父类构造器"); } }
package com.kuangshen.OOP; public class Application { public static void main(String args[]) { people1 person = new people1(); } }
-
super有参构造器
package com.kuangshen.OOP; public class people1 extends people{ public people1() { //影藏代码,调用了父类的构造器 super("人间");//当有参时,如果super不写,那么子类也要变成有参构造,如果写,super要变成有参构造 System.out.println("使用了子类构造器"); } }
package com.kuangshen.OOP; public class people { public people(String a) { System.out.println("使用了父类" + a +"构造器"); } }
package com.kuangshen.OOP; public class Application { public static void main(String args[]) { people1 person = new people1(); } }
-
-
super注意点
- super调用父类的构造方法,必须在构造方法的第一个
- super只能出现在子类的方法或者构造方法中
- super和this不能同时调用构造方法
-
super Vs this
-
代表的对象不同
- this:调用本身的对象
- super:代表父类对象的应用
-
前提:
- this:没有继承也可以使用
- super:只能在继承条件才可以使用
-
构造方法:
- this();本类的构造
- super();父类的构造
-
重写
- 加上static,以下分别为A.java,B.java和Application.java
package com.kuangshen.OOP; public class A extends B{ public static void test() { System.out.println("A"); } }
package com.kuangshen.OOP; public class B { public static void test() { System.out.println("B"); } }
package com.kuangshen.OOP; public class Application { public static void main(String args[]) { //方法的调用只和左边,定义的数据类型有关 A a = new A(); a.test(); B b = new A();//父类的引用指向了子类 b.test(); } }
输出结果为
A
B
-
重写的例子(重写只和非静态有关)
package com.kuangshen.OOP; public class A extends B{ //Override重写 @Override//注解:有功能的注释 public void test() { System.out.println("test=>A"); } }
package com.kuangshen.OOP; public class B { public void test() { System.out.println("test=>B"); } }
package com.kuangshen.OOP; public class Application { public static void main(String args[]) { //方法的调用只和左边,定义的数据类型有关 A a = new A(); a.test(); B b = new A();//非静态时,子类重写了父类的方法,结果只和子类的结果有关 b.test(); } }
最终的结果为:
A
A
-
重写的注意点:需要有继承关系,子类继承父类的方法
- 方法名必须相同
- 参数列表必须相同(否则就是重载)
- 修饰符:范围可以扩大但不可以缩小:public>Protected>Default>private
- 抛出的异常:范围可以缩小但不可以扩大
-
重写,子类和父类必须要一致,但方法体不同
-
为什么需要重写:父类的方法,子类不一定需要,或者不一定满足
多态
- 多态,即同一方法根据发送对象的不同而采用不同的行为方式。
- 一个对象的实际类型是确定的,但可以指向对象的引用类型有很多(父类、有关系的类)
- Student.java,Person.java和Application.java的案例如下:
package com.kuangshen.OOP; public class Student extends Person{ @Override public void run() { System.out.println("Student"); } public void eat() { System.out.println("eat"); } }
package com.kuangshen.OOP; public class Person { public void run() { System.out.println("Person"); } }
package com.kuangshen.OOP; public class Application { public static void main(String args[]) { Student s1 = new Student(); Person s2 = new Student(); Object s3 = new Student(); //对象能执行哪些方法,只能看对象左边的类型,和右边关系不大 s1.run(); s2.run(); s1.eat(); ((Student) s2).eat();//父类无法调用子类的方法,只能强制转换成子类 //s2.eat;//会报错 } }
输出结果:
Student
Student
eat
eat
-
多态注意事项:
- 多态是方法的多态,属性没有多态
- 多态两个类之间有继承关系,如父类和子类
- 存在条件:两类之间继承关系;方法需要重写;父类的引用指向子类,如:Father f1 = new Son();
-
以下方法无法重写,自然没有多态
- static方法,属于类,它不属于实例
- final常量
- private方法
instanceof
直接看例子:
package com.kuangshen.OOP; public class Application { public static void main(String args[]) { Object object = new Student(); System.out.println(object instanceof Student); System.out.println(object instanceof Person); System.out.println(object instanceof Object); System.out.println(object instanceof Teacher); System.out.println(object instanceof String); System.out.println("======================="); Person person = new Student(); System.out.println(person instanceof Student); System.out.println(person instanceof Person); System.out.println(person instanceof Object); System.out.println(person instanceof Teacher); //System.out.println(person instanceof String);//编译失败 System.out.println("======================="); Student student = new Student(); System.out.println(student instanceof Student); System.out.println(student instanceof Person); System.out.println(student instanceof Object); //System.out.println(student instanceof Teacher);//编译失败 //System.out.println(student instanceof String);//编译失败 //Object > String //Object > Student > Person //Object > Teacher > Person } }
我们可以发现,对于A a = new B()[其中A是B的父类或A = B]中,如果A和B没有父子关系,那么编译失败。在后面的(a instanceof C)中如果B是C的子类或者B=C,那么返回值为true,否则返回值为false
类型强制转换
先看例子:
package com.kuangshen.OOP; public class Application { public static void main(String args[]) { Person person = new Student(); ((Student) person).eat(); } }
当父类转化为子类时,要强制转换,本质原因是子类可以调用父类的方法,但父类不可以调用子类的方法。
注意点:
- 父类引用指向子类的对象
- 把子类转换为父类,向上转型,不用强制转换
- 把父类转换为子类,向下转型,需要强制转换
- 强制转换的目的是为了方便方法的调用,减少重复的代码
static关键字
- 静态static和类名一起加载在内存中,所以使用时有一些好用的特性。
package com.kuangshen.OOP; public class Bus { private static int age; private double score; public void run() {} public static void go() {} public static void main(String args) { Bus bus = new Bus(); System.out.println(Bus.age);//对于静态变量,可以用类名直接调用。一般工作时尽量这样调用,方便知道这个age是静态变量。 //System.out.println(Bus.score);//报错 System.out.println(bus.age); System.out.println(bus.score); bus.run(); bus.go();//一般都是这样调用 //Bus.run();//这样会报错 Bus.go();//static的特性可以用类名直接调用 go();//由于main函数在类名中,所以可以前面不加类名直接调用,所以这种格式不能在别的.java文件中这样写 } }
- 静态代码块
package com.kuangshen.OOP; public class Bus { //顺序2:一般用来赋初值 { System.out.println("匿名代码块"); } //顺序1:只执行依次 static { System.out.println("静态代码块"); } public Bus(){ System.out.println("构造方法"); } public static void main(String args[]) { Bus bus1 = new Bus(); System.out.println("========="); Bus bus2 = new Bus(); } }
最终输出结果如下:
静态代码块
匿名代码块
构造方法
@@@@@@@@@@@@@@@@@@@@
匿名代码块
构造方法
- 静态导入包
final特性
如果一个类用了final关键字,就不能被继承。
package com.kuangshen.OOP; public final class Person { public void run() { System.out.println("Person"); } }
package com.kuangshen.OOP; public class Student extends Person{//这里会报错,无法继承有final关键字的(常量无法被继承) @Override public void run() { System.out.println("Student"); } public void eat() { System.out.println("eat"); } }
抽象类
例子:
package com.kuangshen.OOP; public abstract class Action { public abstract void dosomething(); }
package com.kuangshen.OOP; public class ActionMain extends Action { //当一个子类继承了抽象类时会报错,必须要重写抽象方法。 //如果子类也是抽象类,那么要在子子类去重写抽象方法 @Override public void dosomething() { } }
- 不能new这个抽象类,只能靠子类去实现它。
- 抽象类中可以写普通的方法。
- 抽象方法必须写在抽象类中。
抽象类的用处:比如你开发一个游戏,不同的游戏任务某项数据不一样,那么利用抽象类方法名不变,只需要在其继承中重写方法就可以了,本质是为了提高开发效率。
抽象类需要继承,由于java中都是单继承,所以泛用性大大降低;因为接口可以多继承,所以java中最常用到的是接口。
接口
- 接口可以理解为一种特殊的类,里面全部是由****全局常量*和公共的抽象方法所组成。接口是解决***Java无法使用多继承*的一种手段,但是接口在实际中更多的作用是*制定标准*的。或者我们可以直接把接口理解为*100%的抽象类****,既接口中的方法****必须全部****是抽象方法。
- 接口注意点:
- 接口是为了定义一些方法,让不同的人去实现
- 接口中默认的方法都是public abstract
- 接口中的常量都是public static final
- 接口和抽象类一样不能被实例化,因为接口中没有构造方法
- 通过implements关键字可以实现多个接口
- 实现接口时必须要重写接口里面的方法
下面是userService.java,timeService.java,userServiceImpl.java的例子
package com.kuangshen.OOP.demo01; public interface UserService {//接口通过interface定义 public abstract void a();//在IDEA中,接口中的方法都默认公共并且抽象的,所以public和abstract可以不写 void add(); void delete(); void update(); void query(); }
package com.kuangshen.OOP.demo01; public interface TimeService { void timer(); }
package com.kuangshen.OOP.demo01; public class UserServiceImpl implements UserService, TimeService {//接口可以多继承 @Override public void a() { } @Override public void add() { } @Override public void delete() { } @Override public void query() { } @Override public void update() { } @Override public void timer() { } }
内部类
package com.kuangshen.OOP.neibulei; 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); } } }
package com.kuangshen.OOP.neibulei;public class MainClass { public static void main(String args[]) { Outer outer = new Outer(); outer.out(); Outer.Inner inner = outer.new Inner();//内部类的定义方法 inner.in(); inner.getID(); }}
输出结果:
这是外部类的方法
这是内部类的方法
10
这篇关于java面向对象的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-19JAVA分布式id教程:轻松入门与实践
- 2024-11-19Java高并发教程:入门与实践指南
- 2024-11-19JAVA高并发直播教程:新手入门指南
- 2024-11-19Java高并发直播教程:入门与实践指南
- 2024-11-19Java微服务教程:初学者快速入门指南
- 2024-11-19JAVA微服务教程:新手入门的详细指南
- 2024-11-19Java微服务教程:从零开始搭建你的第一个微服务应用
- 2024-11-19Java项目开发教程:初学者必备指南
- 2024-11-19Java项目开发教程:新手快速入门指南
- 2024-11-19Java项目开发教程:零基础入门到实战