目录:
一.初始面向对象
二.方法的回顾和加深
三.对象的创建和分析
四.面向对象三大特性
五.抽象类和接口
六.内部类及OOP实战
学习内容:
一. 初始面向对象:
面向过程&面向对象的思想:
面向过程思想: 步骤清晰简单,第一步做什么,第二步做什么 。面向过程适合处理一些较为简单的问题。
面向对象思想: 物以类聚,分类的思维模式,思考问题首先会解决问题需要哪些分类,然后对这些分类进行独立的思考。最后,才对某个分类下的细节进行面向过程的思索。面向对象适合处理复杂的问题,,适合处理需要多人协作的问题。
例子: 比如说,我们要建一栋大楼,需要进行分工合作。一部分的人进行材料的购买,一部分的人进行建造地基。一部分的人进行主体施工等等... 这一个分类的思想就是面向对象的思想。而当我们进行主体施工时候,所运用的就是面向过程的思想。主体施工的第一步先干什么..第二步在干什么....
什么是面向对象(OOP:面向对象编程):
本质:以类的方式组织代码,以对象的组织封装数据。
三大特性 :封装(假如你有一百万块钱,你就要把他藏起来,不给别人发现,而给自己留一个取用的通道) 继承(儿子继承父亲的东西) 多态(同一个事物被不同的人表现出来有多种形态。一个好的学习方法, 小明去使用 可能成绩变得很好,而小红去使用成绩可能变得很差)
核心思想:抽象。 比如说要设计一个学生管理系统,我们只需要关心学生的学号,名字。而不用去关心学生的爱好,把需要的属性形成一个类,就是抽象(抽取像的东西)。
总结:
- 从认识论的角度是先有对象后有类,对象是具体的事物,类是抽象的,是对对象的抽象。
- 从代码的运行角度是先有类后又有对象,类是对象的模板。
二.方法的回顾和加深
方法的定义和方法的调用:
方法的定义:
- 修饰符、
- 返回类型、
- break和return的区别: break跳出switch语句结束循环 。return 结束方法返回结果
- 方法名:见名知意原则
- 参数列表 (参数类型 String 参数名)
- 异常抛出: 数组下标越界 Arrayindexoutofbounds
方法的定义(代码区):
package com.oop.demo01;
public class fangfa {
//修饰符 返回值类型 方法名(...){ }
//方法体
//return 返回值 结束方法 返回结果
//void 什么都不用返回
//break 跳出switch 结束循坏
public static void qiujinhao (){
}
private static void qiujinhao1(){
}
public String qiujinhao2(String A){
return A;
}
}
方法的调用:
- 静态方法(含static)
- 非静态方法 (不含static)
- 形参和实参
- 值传递和引用传递
- this 关键词
静态方法和非静态方法:
在不同类当中,静态方法的调用可以直接使用“类名.方法名” 非静态方法的调用要new出类的实例化,再通过“对象.方法名”调用 :
在同一个类当中,只有静态方法不可以调用非静态方法外,其他的调用都可以:
package com.oop.demo01;
public class fangfa {
public static void jingtaifangfa (){
//静态方法
}
public void feijingtaifangfa(){
//非静态方法
System.out.println("有人在说话");
}
public void a(){
b();
}
public void b(){
a();
//当两个都是 非静态方法时 ,这两个方法可以相互调用
}
public static void c(){
D();
}
public static void D(){
c();
//当两个都是静态方法时,这两个方法也可以相互调用
}
public static void e(){
}//静态方法不可以调用非静态方法,而非静态方法可以调用静态方法
public void f(){
e();
}
}
形参和实参:
注意点:形式参数和实际参数的类型要对应!
package com.oop.demo01;
public class fangfa {
public static void main(String[] args) {
fangfa s1=new fangfa();
int a=1;
int b=2;
int jisuan = s1.jisuan(1, 2);
//这里赋值后a和b时实际参数
System.out.println(jisuan);
}
public int jisuan(int a, int b) {
//这里的a和b就是形式参数
return a+b;
}
}
值传递和引用传递:
值传递:
package com.oop.demo01;
public class fangfa {
public static void main(String[] args) {
int a=1;
System.out.println(a);
fangfa.change(a);
System.out.println(a);
}
//返回值为空
public static void change(int a){
a=10;
}
}
引用传递:传递对象,本质还是值传递
类与对象的创建:
- 类是一种抽象的数据类型,他是对某一类事物整体描述/定义,但是并不能代表某一个具体的事物。例如 person类,pet类, car类。这些类都是用来描述/定义某一类具体事务应该具备的特点和行为。
- 对象是抽象概念的具体实例。
创建与初始化对象:
使用new关键字创建对象,使用new关键字创建的时候,除了分配内存空间之外,还会给创建好的对象进行默认的初始化以及对类中构造器的调用。
package com.oop.demo01;
public class fangfa {
public static void main(String[] args) {
int a=0;
//a是引用
fangfa s1 = new fangfa();
//new关键词实例化了一个对象
//类名 对象名=new 类型
}
}
构造器详解:
类中的构造器也称为构造方法,是在创建对象的时候必须要调用的,并且构造器有以下两个特点:1.必须和类的名字相同,2.必须没有返回类型,也不能写void。
package com.oop.demo01;
public class fangfa {
public static void main(String[] args) {
}
public fangfa() {
//构造函数
//快捷键:alt+insert
//一个类即使什么都不写,他也存在构造器。
//无参构造的作用:使用new关键字的时候,本质在调用构造器。初始化对象的值
}
//注意点:一旦定义了有参构造,无参构造就必须显示出来,不然会报错
public fangfa(String name){
this.name=name;
}
}
创建对象内存分析:
package com.oop.demo01;
public class fangfa {
String name;
int age;
public void shout(){
System.out.println("叫了一声");
}
}
package com.oop.demo01;
public class application2 {
public static void main(String[] args) {
fangfa person = new fangfa();
person.name="xiaohong";
person.age= Integer.parseInt("3");
System.out.println(person.name);
System.out.println(person.age);
fangfa teacher= new fangfa();
}
}
下面是对上面代码的简单对象内存分析图
封装详解:
该露的露,该藏得藏:
- 我们程序设计要追求:高内聚低耦合。高内聚就是类的内部数据操作细节自己完成,不允许外部干涉。低耦合,仅暴露少量的方法给外部使用
- 封装(数据的隐藏),通常应该禁止直接访问一个对象中数据的实际表示,而应该操作接口来访问,这称为信息隐藏
属性私有:get/set
package com.oop.demo01;
public class fangfa {
//一般私有都是私有属性,不是私有方法
private int age;
private String name;
public void shout() {
System.out.println("叫了一声");
}
public String getName(){
return this.name;
}
public String setName(String name){
return this. name=name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
if(age<0||age>120){
this.age = Integer.parseInt("3");
}else{
this.age= age;
}
}
}
package com.oop.demo01;
public class application2 {
public static void main(String[] args) {
fangfa s1 = new fangfa();
s1.shout();
//get/set提供一些可以操作这个属性的方法
//get获得这个数据,set 给这个数据赋值
s1.setName("qiujinhao");
System.out.println(s1.getName());
s1.setAge(Integer.parseInt("130"));
System.out.println(s1.getAge());
}
}
//alt+insert可以自动生成get set方法
/*
封装的意义:
1.提高程序的安全性,保护数据
2.隐藏代码的实现细节
3.统一接口
4.系统的可维护性增加
*/
继承:
- 继承的本质是对某一批类的抽象,从而实现对现实世界更好的建模。
- extends的意思是“扩展”子类是父类的扩展
- java中类只有单继承,没有多继承(比如说:一个儿子只能有一个爸爸,而一个爸爸可以用很多儿子)
- 继承是类和类之间的一种关系,除此之外,类和类之间的关系还有依赖,组合,聚合等
- 继承关系的两个类,一个为子类(派生类),一个为父类(基类),子类继承父类,用关键字extends来表示
- 子类和父类之间,从意义上讲应该具有“is a”的关系
子类:
package com.oop.demo01;
// 子类继承父类
//子类可以继承父类的所有方法
//在java 中 所有类都默认继承objec类
public class erzi extends fuqin{
}
父类:
package com.oop.demo01;
public class fuqin {
public int money=1000;
private int car;
public void shout() {
System.out.println("有人再叫");
}
public int getCar() {
return car;
}
public void setCar(int car) {
this.car = car;
}
}
应用类
package com.oop.demo01;
public class application4 {
public static void main(String[] args) {
erzi erzi = new erzi();
erzi.shout();
System.out.println(erzi.money);
erzi.setCar(Integer.parseInt("3"));
System.out.println(erzi.getCar());
}
}
super和this的区别详解
1.在属性方面的应用:
package com.oop.demo01;
// 子类继承父类
//子类可以继承父类的所有方法
//在java 中 所有类都默认继承objec类
public class erzi extends fuqin{
String name="xiaohong";
public void test(String name){
System.out.println(name);
System.out.println(this.name);
System.out.println(super.name);
}
}
ackage com.oop.demo01;
public class fuqin {
public int money=1000;
private int car;
protected String name="qiujinhao";
public void shout() {
System.out.println("有人再叫");
}
public int getCar() {
return car;
}
public void setCar(int car) {
this.car = car;
}
}
package com.oop.demo01;
public class application4 {
public static void main(String[] args) {
erzi erzi = new erzi();
erzi.test("丘锦豪");
}
}
输出结果:
2.在方法方面的应用:
package com.oop.demo01;
// 子类继承父类
//子类可以继承父类的所有方法
//在java 中 所有类都默认继承objec类
public class erzi extends fuqin{
public void print(){
System.out.println("a");
super.print();
}
}
package com.oop.demo01;
public class fuqin {
public void print() {
System.out.println("打印这本书");
}
}
package com.oop.demo01;
public class application4 {
public static void main(String[] args) {
erzi erzi = new erzi();
erzi.print();
}
}
继承在构造器上的使用:
package com.oop.demo01;
// 子类继承父类
//子类可以继承父类的所有方法
//在java 中 所有类都默认继承objec类
public class erzi extends fuqin{
public erzi() {
System.out.println("子类调用无参构造");
}
}
package com.oop.demo01;
public class fuqin {
public fuqin() {
System.out.println("父类调用无参构造");
}
}
package com.oop.demo01;
public class application4 {
public static void main(String[] args) {
erzi erzi = new erzi();
}
}
结果:
总结:
调用erzi类的时候,结果先输出了fulei的无参构造。说明在zilei的无参构造中调用了fulei的无参构造,使用super关键词调用。且调用父类构造器的时候,必须在子类构造器的第一行。
super总结:
- super调用父类的构造方法,必须在构造方法的第一个
- super必须只能出现在子类的方法或者构造方法中
- super和this不能同时调用构造方法
vsthis:
代表的对象不同:
this:本身调用者这个对象
super:代表父类对象的应用
前提
this:没有继承也可以使用
super:只能在继承条件下才可以使用
构造方法:
this();调用本来的构造
super()调用父类的构造
方法的重写:
当为静态方法的时候:
package com.oop.demo01;
// 子类继承父类
//子类可以继承父类的所有方法
//在java 中 所有类都默认继承objec类
public class erzi extends fuqin{
public static void print(){
System.out.println("子类的方法");
}
}
package com.oop.demo01;
public class fuqin {
public static void print(){
System.out.println("父类的方法");
}
}
package com.oop.demo01;
public class application4 {
public static void main(String[] args) {
erzi A = new erzi();
fuqin B = new fuqin();
A.print();
B.print();
}
}
输出结果:
因为A属于erzi类 调用erzi类的方法。B属于fuqin类,调用fuqin类的方法。静态方法是类的方法
当为非静态方法时候 : 需要重写:(erzi类和fulei类的代码不作变动)
package com.oop.demo01;
// 子类继承父类
//子类可以继承父类的所有方法
//在java 中 所有类都默认继承objec类
public class erzi extends fuqin{
//快捷键 alt+insert
@Override//重写的标志
public void print() {
System.out.println("子类的方法");
}
}
package com.oop.demo01;
public class fuqin {
public void print(){
System.out.println("父类的方法");
}
}
/* 即b是A new出来的对象,因此调用了A的方法
因为静态方法是类的方法,而非静态是对象的方法
有static时,b调用了B类的方法,因为b是用b类定义的
*/
package com.oop.demo01;
public class application4 {
public static void main(String[] args) {
fuqin A = new erzi();//子类重写了父类的方法
fuqin B = new fuqin();
A.print();
B.print();
}
}
结果:
分析: 在 fuqin A=new erzi(); 中,子类重写了父类的方法。非静态方法是对象的方法
总结:重写:需要有继承关系,子类重写父类的方法!
1.方法名必须相同
2.参数列表必须相同
3.修饰符:范围可以扩大。(public>protected>Default>private)
4.抛出的异常:范围:可以被缩小,但不能被扩大
重写:子类的方法和父类必须要一致,方法体可以不同
多态:
- 即同一个方法可以根据发送对象的而不同而采用多种不同的行为方式
- 一个对象的实际类型是确定的,但可以指向对象的引用的类型有很多
instance of 和类型转换 :
instance of 分为两个过程:
1.是否编译成功 2. 编译成功后true与false 的区别
下面代码详解:
package com.oop.demo01;
import jdk.swing.interop.SwingInterOpUtils;
public class application4 {
public static void main(String[] args) {
//object>fuqin>erzi
//object>fuqin>daerzi
//object>string
Object s1 = new erzi();
System.out.println(s1 instanceof Object);//true
System.out.println(s1 instanceof erzi);//true
System.out.println(s1 instanceof fuqin);//true
System.out.println(s1 instanceof daerzi);//false
System.out.println(s1 instanceof String);//false
System.out.println("================================");
/*
编译都通过的原因:
编译的时候,看引用变量名属于谁的类,再看这个类与 instanceof xxx类是否有关系
如何判断结果是true 还是false:
看引用变量名的对象 是否继承了 instanceof xxx类
比如说:s2的实例化对象是fuqin ,instanceof erzi类 ,s2的对象没有继承 erzi 类
,则结果为false。
若存在 则 true
若不存在 则falese
*/
fuqin s2 = new fuqin();
System.out.println(s2 instanceof Object);//true
System.out.println(s2 instanceof erzi);//false
//s2的对象是fuqin类,是erzi类继承fuqin类,所以s2的对象 没有继承 erzi类,则false
System.out.println(s2 instanceof fuqin);//true
System.out.println(s2 instanceof daerzi);//false
System.out.println("==============================");
//编译报错System.out.println(s2 instanceof String);
erzi s3 = new erzi();
System.out.println(s3 instanceof Object);//true
System.out.println(s3 instanceof erzi);//true
System.out.println(s3 instanceof fuqin);//true
//编译报错System.out.println(s3 instanceof daerzi);
//编译报错System.out.println(s3 instanceof String);
}
}
强制转换:
当父类想要调用子类的方法的时候,向下转型,需要强制转换
当子类想要调用父类的方法的时候,向上转型可能会丢失一些方法(当子类方法和父类方法同名时候,这时候只能调用子类的方法)
子类:
package com.oop.demo01;
import javax.crypto.spec.PSource;
// 子类继承父类
//子类可以继承父类的所有方法
//在java 中 所有类都默认继承objec类
public class erzi extends fuqin{
//快捷键 alt+insert
public void print() {
System.out.println("子类的方法");
}
public void run() {
System.out.println("so");
}
}
父类:
package com.oop.demo01;
public class fuqin {
public void shout(){
System.out.println("父类的方法");
}
}
应用类:
package com.oop.demo01;
public class application5 {
public static void main(String[] args) {
erzi s1 = new erzi();
s1.shout();
// 子类可以调用父类的方法
fuqin s2 = new fuqin();
//编译失败,父类不能调用子类s2.run;所以需要强制转换
//父类转子类,需要强制转换
erzi s3=(erzi) s2;
s3.run();
s3.print();
}
}
static关键词详解:
- 当变量为静态的时候,一般调用变量的时候,都使用类去调用这个静态变量(因为static是和类一起加载的)
- 在同一个类中,非静态方法可以调用静态方法。静态方法不能调用非静态方法
抽象类:
关键词:abstract
-
抽象类的特点: 不能new这个抽象类 ,只能拿子类去实现它 抽象类里面可以写普通方法 抽象方法必须在抽象类中!
package com.oop.demo01;
public abstract class chouxiang {
//抽象方法 只有方法名字,没有方法的实现
public abstract void shout();
/*
抽象类的特点:
不能new这个抽象类 ,只能拿子类去实现它
抽象类里面可以写普通方法
抽象方法必须在抽象类中!
*/
}
接口:
- 关键字 interface
- 普通类:只有具体的实现
- 抽象类:具体实现和规范(抽象方法)都有
- 接口:只有规范(抽象方法)自己无法写方法 ,专业的约束 ,约束和实现分离,面向接口编程。
作用:
- 约束
- 定义一些方法,让不同的人去实现
- 方法都是public abstract
- 常量都是 public static final
- 接口不能够被实例化~接口中没有构造方法
- implement关键词可以实现多个接口
- implement后必须要重写接口的方法,不然会报错
内部类:
- 成员内部类80/0
- 静态内部类
- 局部内部类
- 匿名内部类