摘要:面向对象之封装继承多态封装将类中的信息进行隐藏在类的内部,不允许外部程序信息直接访问,而是只能通过该类的提供的方法来实现对隐藏信息的提供和访问。与之对应,包含内部类的类被称为外部类。
面向对象之封装、继承、多态 封装
将类中的信息进行隐藏在类的内部,不允许外部程序信息直接访问,而是只能通过该类的提供的方法来实现对隐藏信息的提供和访问。
好处
只能隐藏规定的方法和数据 隐藏类的实现细节,方便修改和实现
封装的实现步骤
1. 用private等修饰符修饰属性 2. 创建属性的getter/setter方法 3. 在getter/setter方法中加入属性的控制语句java中的访问修饰符
java中的访问修饰符一个有四个,我们主要学习private、protected、public三个。java中的this关键字
this关键字代表当前对象
this.属性 操作当前对象的属性 this.方法 操作当前对象的方法
封装对象的属性的时候会经常使用this关键字
package com.test.cat; // 定义包 public class Cat { int a; int b; public void send() { System.out.print("send"); } public int getA() { this.send(); // 调用方法 return a; } public void setA(int a) { this.a = a; // 调用属性 } public int getB() { return b; } public void setB(int b) { this.b = b; } public Cat() { System.out.println("Cat 实例化了"); } }java中的内部类
内部类( Inner Class )就是定义在另外一个类里面的类。与之对应,包含内部类的类被称为外部类。
内部类的主要作用
1. 内部类提供了更好的封装,可以把内部类隐藏在外部类之内,不允许同一个包中的其他类访问该类 2. 内部类的方法可以直接访问外部类的所有数据,包括私有的数据 3. 内部类所实现的功能使用外部类同样可以实现,只是有时使用内部类更方便
内部类的分类
成员内部类 静态内部类 方法内部类 匿名内部类
先举个例子
//外部类HelloWorld public class HelloWorld { // 内部类Inner,类Inner在类HelloWorld的内部 public class Inner { // 内部类的方法 public void show() { System.out.println("welcome to imooc!"); } } public static void main(String[] args) { // 创建外部类对象 HelloWorld hello = new HelloWorld(); // 创建内部类对象 Inner i = hello.new Inner(); // 调用内部类对象的方法 i.show(); } }java中的成员内部类(普通内部类)
package innerClass; // 外部类 public class Outer { private int out; // 外部类成员 private int b; // 外部的b public int getOut() { return out; } public void setOut(int out) { this.out = out; } // 外部类构造函数 public Outer(int _out) { this.out = _out; System.out.println("外部类实例化中....."); // 外部类则无法访问内部类的数据 } // 内部类 public class Inner{ private int in; // 内部类成员 private int b; // 内部的b // 内部类构造函数 public Inner(int _in) { this.in = _in; System.out.println("内部类实例化中...."); System.out.println(out); // 内部类可以访问外部类中的任何数据 System.out.println(this.b); // 如果遇上重名,那么默认是使用内部的变量,如果想要使用外部的变量,可以使用this } } public static void main(String [] args) { Outer o = new Outer(100); // 创建一个外部对象 System.out.println(o.getOut()); Inner i = o.new Inner(200); // 创建一个内部对象 } }
注意事项
1. Inner 类定义在 Outer 类的内部,相当于 Outer 类的一个成员变量的位置,Inner 类可以使用任意访问控制符,如 public 、 protected 、 private 等 2. Inner 类中定义的 test() 方法可以直接访问 Outer 类中的数据,而不受访问控制符的影响 3. 定义了成员内部类后,必须使用外部类对象来创建内部类对象,而不能直接去 new 一个内部类对象,即:内部类 对象名 = 外部类对象.new 内部类( ); 4. 编译上面的程序后,会发现产生了两个 .class 文件 其中,第二个是外部类的 .class 文件,第一个是内部类的 .class 文件,即成员内部类的 .class 文件总是这样:外部类名$内部类名.class
外部类是不能直接使用内部类的成员和方法滴
如果外部类和内部类具有相同的成员变量或方法,内部类默认访问自己的成员变量或方法,如果要访问外部类的成员变量,可以使用 this 关键字。
Java 中的静态内部类静态内部类是 static 修饰的内部类
特点
1. 静态内部类不能直接访问外部类的非静态成员,但可以通过 new 外部类().成员 的方式访问 2. 如果外部类的静态成员与内部类的成员名称相同,可通过“类名.静态成员”访问外部类的静态成员;如果外部类的静态成员与内部类的成员名称不相同,则可通过“成员名”直接调用外部类的静态成员 3. 创建静态内部类的对象时,不需要外部类的对象,可以直接创建 内部类 对象名= new 内部类();
package static_inner_class; public class Outer { private int a; // 外部普通成员变量 static int b = 10; //外部静态变量 public Outer(int _a) { this.a = _a; System.out.println("外部类实例化中...."); } // 内部类 public static class Inner{ private int b; public Inner(int _b) { this.b = _b; System.out.println("内部类实例化中...."); } public void test() { System.out.println("访问外部类中的b:" + Outer.b); // 访问外部静态变量,建议使用class.staticName ,即使这是处理外部类和内部类存在同名变量的情况下 System.out.println("访问内部类中的b:" + b); // 访问内部变量可以直接访问 } } public static void main(String [] args) { Outer o = new Outer(10); Inner i = new Inner(20); // 创建内部类可以直接使用该方法,不用先实例化外部类 i.test(); } }Java 中的方法内部类
方法内部类就是内部类定义在外部类的方法中,方法内部类只在该方法的内部可见,即只在该方法内可以使用。
//外部类 public class HelloWorld { private String name = "爱慕课"; // 外部类中的show方法 public void show() { // 定义方法内部类 class MInner { int score = 83; public int getScore() { return score + 10; } } // 创建方法内部类的对象 MInner mi=new MInner(); // 调用内部类的方法 int newScore=mi.getScore(); System.out.println("姓名:" + name + " 加分后的成绩:" + newScore); } // 测试方法内部类 public static void main(String[] args) { // 创建外部类的对象 HelloWorld mo=new HelloWorld(); // 调用外部类的方法 mo.show(); } }继承
继承就是类与类之间的一种 is a的关系
java中继承是单继承的,也就是只能由一个父类
好处
1. 实现代码的复用 2. 子类拥有父类的所有属性和方法 3. 但是private修饰的属性和方法却无法访问到
语法规则
例子
// Animal.java package inhert_demo1; public class Animal { public int age; public String name; public void eat() { System.out.println("动物可以吃东西"); } }
// Cat.java package inhert_demo1; public class Cat extends Animal{ // 【方法的重写】 public void eat() { System.out.println("猫咪可以吃东西"); } }
// test.java package inhert_demo1; public class test { public static void main(String [] args) { Cat c = new Cat(); c.eat(); } }方法的重写
如果子类对继承父类的方法不满意,是可以重写父类的方法的,当调用的时候,优先调用子类的方法
// 规定 1. 返回值相同 2. 参数类型及个数相同 3. 方法名相同继承的出发顺序
1. 先初始化父类,然后再初始化子类 2. 先执行初始化对象中的属性,然后再执行构造函数中的初始化
// 执行顺序为 package inhert_demo1; public class Animal { public int age = 10; //【1】 属性初始化 public String name; public Animal() { age = 20; // 【2】构造函数中的初始化 } public void eat() { System.out.println("动物可以吃东西"); } }final "最终的"
final可以修饰类、属性、方法、变量
final修饰的类,则该类不能被继承 final修饰的方法,则方法不允许被覆盖(也就是方法的重写) final修饰的属性: 属性初始化必须是在属性初始化或者构造方法中初始化,只能人选其一 final修饰的变量,这个变量就成为了常量,只能赋值一次super
super关键字代指父类 (在对象内部使用、可以代表父类对象)
// 子类 cat package inhert_demo1; public class Cat extends Animal{ public int age = 20; public void eat() { System.out.println("猫咪可以吃东西"); } public void meyhod () { // super代表父类 System.out.println(super.age); // 使用父类的属性 super.eat(); // 子类中调用父类的方法 } }
注意
1. 如果子类中的构造方法没有显示的调用父类的构造方法,那么系统将默认调用父类的无参构造方法 也就是会隐世的调用`super()` 2. 如果父类没有无参构造方法,而是有有参的构造方法,那么子类中就必须显示的调用父类的构造方法。Object类
Object类是所有类的父类,如果一个类没有明确的使用extends来指定继承一个类,那么这个类默认继承Object(Object类中的方法适合子类)
方法一、toString()
Object中的类方法toString()返回的是一个对象的哈希Code码(对象的地址引用) // 我们则是想使用该方法来返回属性的值,因此我们可以重写该方法 // cat类中 public String toString() { return "Cat [age=" + age + "]"; } //使用 package inhert_demo1; public class test { public static void main(String [] args) { Cat c = new Cat(); System.out.println(c.toString()); } }
方法二、equals()
比较对象的引用是否指向同一块内存地址。
Dog d1 = new Dog(); Dog d2 = new Dog(); d1.d2是两个地址,是不相同的 // 如果我们想要用equals来比较两个对象的值是否相同,这就需要我们重写该方法
// cat中重写 @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass())// getClass 获取到的是类对象 return false; Cat other = (Cat) obj; if (age != other.age) return false; return true; }
Cat c = new Cat(); System.out.println(c.toString()); Cat c1 = new Cat(); if(c1.equals(c)) { System.out.println("两个对象的属性相同"); }
补充 getClass 获取到的是类对象
多态多态指的是对象的多种形态
1. 引用多态 父类的引用可以指向子类的对象 父类的引用可以指向本类的对象 public static void main(String [] args) { Animal d1 = new Animal(); Animal d2 = new Dog(); Dog d3 = new Animal(); // 报错了,因为是子类的引用指向了父类的对象 } 2. 方法多态 创建本类对象时,调用的时本类的方法 创建子类对象时,调用的方法时子类重写的方法或者时父类继承过来的方法 Animal d1 = new Animal(); Animal d2 = new Dog(); d1.eat(); // 调用父类的eat方法 d2.eat(); // 调用子类重写的eat方法多态中的引用类型转换
1. 向上类型转换(隐式/自动类型转换) 小类型 => 大类型 2. 向下类型转换(强制类型转换) 大类型 => 小类型 3. instanceof可以解决引用对象的类型,来避免转换类型的安全性问题
package polymorphic; public class test { public static void main(String [] args) { Dog dog = new Dog(); Animal animal = dog; // 小类型 => 大类型 // Dog dog2 = animal; // 报错了,因为大类型 => 小类型 存在风险 Dog dog2 = (Dog)animal; // 强制类型转换,就不报错了 // Cat cat =(Cat) animal; // 编译时Cat类型,运行时时Dog类型 if(animal instanceof Dog) { } else { } } }抽象类
使用abstract修饰的类成为抽象类
1. 某一个父类只知道子类应该含有怎样的方法,但是无法确定这个子类的方法如何实现 2. 从多个具有相同特征的类中抽象出一个抽象类,以这个抽线类作为子类的模板,从而避免了子类设计的随意性
使用规则
abstract定义抽象方法,只有声明、不需要实现 抽象类中可以有普通方法,也可以有抽象方法 抽象类不能直接创建,我们可以定义引用变量
public abstract class telphone { // 定义抽象方法 public abstract void call(); public abstract void message(); // 抽象方法没有方法体,因此以分号结束 }
实例
// Telphone.java package abstrated; public abstract class Telphone { // 定义抽象方法 public abstract void call(); public abstract void message(); // 抽象方法没有方法体,因此以分号结束 }
// Cellphone.java package abstrated; public class Celltelphone extends Telphone { public void call() { System.out.println("通过键盘打电话"); } public void message() { System.out.println("通过键盘发短信"); } }
// smartphone.java package abstrated; public class Smarttelphone extends Telphone{ public void call() { System.out.println("通过语音打电话"); } public void message() { System.out.println("通过语音发短信"); } }
// initial.java package abstrated; public class initial { public static void main(String[] args) { // TODO Auto-generated method stub Telphone t1 = new Celltelphone(); // 使用父类的引用创建子类对象 t1.call(); t1.message(); Telphone t2 = new Smarttelphone(); // 使用父类的引用创建子类对象 t2.call(); t2.message(); } }接口
接口可以理解为时一种特殊的类,由全局常量和公共的抽象方法来组成
它是类的一种具体实现,而接口定义了某一批类所需要遵守的【规范】,接口并不关心这些类的内部实现,也不关心这些类的实现细节,只是规定了这些类的必须实现的某些方法。
接口定义
interface A{//定义一个接口 public static final String MSG = "hello";//全局常量 public abstract void print();//抽象方法 }
// X.java package interfaceDemo1; interface A{ public static final String MSG = "hello"; // 全局常量 public abstract void print(); // 抽象方法 } interface B{ public static final int a = 10; public abstract void get(); } public class X implements A,B{ // X实现了两个接口 public void print() { System.out.println("接口A的抽象方法print()"); } public void get() { System.out.println("接口B的抽象方法get()"); } }
// test.java package interfaceDemo1; public class test { public static void main(String[] args) { // TODO Auto-generated method stub X x = new X(); // 实例化子类 A a = new X(); B b = new X(); x.print(); x.get(); a.print(); b.get(); } }
未完待续
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/76700.html
摘要:方法即为收集器,它接收高阶函数和的后端掘金年的第一天,我坐在独墅湖边,写下这篇文章。正因如此,所以最全系列教程后端掘金是从版本开始引入的一个新的,可以替代标准的。 设计模式之单例模式 - 掘金前言 作为一个好学习的程序开发者,应该会去学习优秀的开源框架,当然学习的过程中不免会去阅读源码,这也是一个优秀程序员的必备素养,在学习的过程中很多人会遇到的障碍,那就是设计模式。很多优秀的框架会运...
摘要:很多情况下,通常一个人类,即创建了一个具体的对象。对象就是数据,对象本身不包含方法。类是相似对象的描述,称为类的定义,是该类对象的蓝图或原型。在中,对象通过对类的实体化形成的对象。一类的对象抽取出来。注意中,对象一定是通过类的实例化来的。 showImg(https://segmentfault.com/img/bVTJ3H?w=900&h=385); 马上就要到七夕了,离年底老妈老爸...
摘要:很多情况下,通常一个人类,即创建了一个具体的对象。对象就是数据,对象本身不包含方法。类是相似对象的描述,称为类的定义,是该类对象的蓝图或原型。在中,对象通过对类的实体化形成的对象。一类的对象抽取出来。注意中,对象一定是通过类的实例化来的。 showImg(https://segmentfault.com/img/bVTJ3H?w=900&h=385); 马上就要到七夕了,离年底老妈老爸...
摘要:很多情况下,通常一个人类,即创建了一个具体的对象。对象就是数据,对象本身不包含方法。类是相似对象的描述,称为类的定义,是该类对象的蓝图或原型。在中,对象通过对类的实体化形成的对象。一类的对象抽取出来。注意中,对象一定是通过类的实例化来的。 showImg(https://segmentfault.com/img/bVTJ3H?w=900&h=385); 马上就要到七夕了,离年底老妈老爸...
阅读 1636·2021-08-13 15:03
阅读 2059·2019-08-30 15:54
阅读 3519·2019-08-26 10:30
阅读 993·2019-08-26 10:22
阅读 2723·2019-08-23 14:42
阅读 1783·2019-08-22 11:16
阅读 1001·2019-08-21 18:33
阅读 3129·2019-08-21 17:28