大佬教程收集整理的这篇文章主要介绍了「Java基础」六、面向对象 进阶,大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
封装、继承、多态-----------java三大特性
核心:只对需要的类可见,用户无需知道对象内部方法的实现细节,但可以根据对象提供的外部接口(对象名和参数)访问该对象
同时也是为了减少代码冗余
特性:
安全特性;
便于使用特性;
提供重复性的特性;
好处:
- 隐藏信息和实现细节
通过控制访问权限可以将不希望客户端程序员看见的信息隐藏起来(如客户的银行密码需要保密,便需要只对客户开放权限)
- 实现了专业的分工
将能实现某一特定功能的代码封装成一个单独的类,在程序员需要使用的时候可以随时调用,从而实现了专业的分工
- 提高对象数据的安全性
private | default | protected | public | |
---|---|---|---|---|
同一个类 | 可用 | 可用 | 可用 | 可用 |
同一个包中的类 | 可用 | 可用 | 可用 | |
子类 | 可用 | 可用 | ||
其他包中的类 | 可用 |
将多个类具有共同特征和行为封装成一个类,实现一次定义,减少代码冗余,实现了代码的复用性
一个拥有自己独特特征的类(子类 扩展类) 继承(extends) 拥有共同特征的类(父类 基类)
子类继承父类,拥有父类的属性,因而子类的对象可以给共同属性赋值
java中一个类只能继承一个类(单根继承)
继承是一个很普遍的现象:
如果一个类明确指明了继承(extends)自某一个类,则这个类就是他的父类
如果一个类并未通过extends指明继承自某一个类,则这个类继承自Object类(顶级父类---最大的类)
public class Animal { // 父类
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String Name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int agE) {
this.age = age;
}
@Override
public String toString() {
return "Animal{" +
"name='" + name + ''' +
", age=" + age +
'}';
}
}
public class Dog extends Animal{ // 子类
private String type;
public String getType() {
return type;
}
public void setType(String typE) {
this.type = type;
}
@Override
public String toString() {
return "Dog{" +
"type='" + type + ''' +
"} " + super.toString();
}
}
public class Cat extends Animal{
private String address;
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "Cat{" +
"address='" + address + ''' +
"} " + super.toString();
}
}
public class Main { // 测试类
public static void main(String[] args) {
Cat cat = new Cat();
// 共同特征(通过继承获取)
cat.setName("Hello KiTi");
cat.setAge(3);
// 独有特征
cat.setAddress("北京");
System.out.println(cat);
Dog dog = new Dog();
// 共同特征(通过继承获取)
dog.setName("旺财");
dog.setAge(4);
// 独有特征
dog.setType("拉布拉多");
System.out.println(dog);
}
}
同一个行为具有多个不同的表现形式。
封装和继承是多态的表现形式
多态实现的三个充要条件:
- 继承
- 重写父类方法
- 父类引用指向子类对象
此处Fruit apple = new Apple();
父类的引用指向子类的对象,这便是多态的一种体现(向上转型),因为Apple继承与Fruit并重写了eatFruit(),所以能够表现多种状态的形式。
向上转型(小范围 ------> 大范围)
Fruit apple = new Apple();
动态绑定(自动实现的)
向上转型后,用父类的变量接收子类的对象(
Fruit apple = new Apple();
),运行时会找父类类型变量(apple
)中存放数据的实际类型(Apple()
),并执行这个实际类(Apple()
)中的对应方法(eatFruit()
),而不是父类(Fruit
)中的方法(eatFruit()
),用static修饰可以解决此问题
/**
* 水果
*/
public class Fruit {
String fruit; //
public String getFruit() {
return fruit;
}
public void setFruit(String fruit) {
this.fruit = fruit;
}
public void eatFruit(){
System.out.println("吃水果!");
}
@Override
public String toString() {
return "Fruit{" +
"fruit='" + fruit + ''' +
'}';
}
}
/**
* 苹果
*/
class Apple extends Fruit{
private String color; // 颜色
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
@Override
public String toString() {
return "Apple{" +
"color='" + color + ''' +
"} " + super.toString();
}
@Override
public void eatFruit(){
color = "红色";
super.fruit = "苹果";
System.out.println("吃" + color + fruit);
}
}
/**
* 橙子
*/
class Orange extends Fruit{
private String exterior; // 外观
public String getExterior() {
return exterior;
}
public void setExterior(String exterior) {
this.exterior = exterior;
}
@Override
public void eatFruit() {
exterior = "圆的";
super.fruit = "橘子";
System.out.println("吃" + exterior + fruit);
}
@Override
public String toString() {
return "Orange{" +
"exterior='" + exterior + ''' +
"} " + super.toString();
}
}
向上转型会隐藏子类扩展出来的功能
public class Test {
// 将参数列表改为各种水果的父类,只需要定义一次,就可以重复利用,而不需要利用方法重写来实现同一个动作
public static void DoThing(Fruit fruit){
System.out.println("---------------------------------------");
fruit.eatFruit();
System.out.println("---------------------------------------");
}
//--------------------方法重写,会导致代码冗余--------------------
/*public static void DoThing(Orange orangE){
System.out.println("---------------------------------------");
fruit.eatFruit();
System.out.println("---------------------------------------");
}
public static void DoThing(Apple applE){
System.out.println("---------------------------------------");
fruit.eatFruit();
System.out.println("---------------------------------------");
}*/
//--------------------------------------------------------------
}
public static void main(String[] args) {
DoThing(new Apple());
DoThing(new Orange());
}
}
大范围 -----> 小范围 (强制类型转换):把父类说成是子类
向下转型要求:父类必须拥有子类的属性,不能拥有就会出现类型转换异常
向下转型的应用场景
明确知道了传入的数据是什么类型,才能进行向下转型
如果要进行向下转型,必须先向上转型,在向下转型,不然会出错
public class Test {
public static void main(String[] args) {
// Apple apple = (ApplE) new Fruit(); // 单纯的进行强制类型转换会出现异常
Fruit fruit = DoThing(1);
if (fruit instanceof OrangE){
Orange orange = (OrangE) fruit;
System.out.println(orangE);
}else{
Apple apple = (ApplE) fruit;
System.out.println(applE);
}
}
public static Fruit DoThing(int number){
if (number == 0){
Orange orange = new Orange();
orange.setFruit("橘子");
orange.setExterior("圆的");
return orange;
}else{
Apple apple = new Apple();
apple.setFruit("苹果");
apple.setColor("红色");
return apple;
}
}
}
组合就是将对象引用置于新类中。
组合也是一种提高代码复用性的方式。
如果你不想让类有更多的扩展功能,你需要记住一句话多用组合,少用继承
组合和继承是有区别的
特征 | 组合 | 继承 |
---|---|---|
关系 | 组合是一种has - a 的关系,可以理解为有一个 |
继承是一中 is - a 的关系,可以理解为是一个 |
耦合性 | 组合是一种松耦合的关系 | 继承双方紧耦合 |
是否具有多态 | 组合不具备多态和向上转型 | 继承是多态的基础,可以向上转型 |
时期 | 组合是运行期绑定 | 继承是编译期绑定 |
Fruit类引用了Apple类、Orange类,从而调用他们各自的属性和方法
public class Test{
public static void main(String[] args) {
Fruit fruit = new Fruit();
fruit.setFruit("苹果");
Apple apple = new Apple();
apple.setColor("红的");
fruit.setApple(applE);
Orange orange = new Orange();
orange.setExterior("圆的");
fruit.setOrange(orangE);
System.out.println(fruit);
}
}
/**
* 水果
*/
public class Fruit {
private String fruit;
private Apple apple;
private Orange orange;
public Apple getApple() {
return apple;
}
public void setApple(Apple applE) {
this.apple = apple;
}
public Orange getOrange() {
return orange;
}
public void setOrange(Orange orangE) {
this.orange = orange;
}
public String getFruit() {
return fruit;
}
public void setFruit(String fruit) {
this.fruit = fruit;
}
public void eatFruit(){
System.out.println("吃水果!");
}
@Override
public String toString() {
return "Fruit{" +
"fruit='" + fruit + ''' +
", apple=" + apple +
", orange=" + orange +
'}';
}
}
/**
* 苹果
*/
class Apple{
private String color; // 颜色
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
@Override
public String toString() {
return "Apple{" +
"color='" + color + ''' +
'}';
}
}
/**
* 橙子
*/
class Orange{
private String exterior; // 外观
public String getExterior() {
return exterior;
}
public void setExterior(String exterior) {
this.exterior = exterior;
}
@Override
public String toString() {
return "Orange{" +
"exterior='" + exterior + ''' +
'}';
}
}
因为接口不能被实例化,故接口中不能有任何构造方法
如果一个事务只有共同行为(功能)而没有共同特征(属性),则用接口定义
接口注重功能,所以接口中只有方法,且默认为抽象方法(即默认是用
public abstract
修饰的)接口可以多实现(implements)
// 定义接口
public interface Shape {
void area(); // 计算面积
void perimeter(); // 计算周长
}
// 实现接口
public class Circle implements Shape {
@Override
public void area() {
System.out.println("计算Circle的面积");
}
@Override
public void perimeter() {
System.out.println("计算Circle的周长");
}
}
耦合:个体相互之间有依赖关系
好处:
- 便于修改
- 业务并行
- 分工协作
- 通用性强(低耦合)
public class Test {
public static void main(String[] args) {
Computer computer = new Computer();
computer.setMainBoard("I7 的主板"); // 同一块主板可以使用不同的cpu
computer.setCpu(new I3());
computer.getCpu().jiSuan();//调用i3主板的计算功能
computer.setCpu(new I5());
computer.getCpu().jiSuan();//i5主板的计算功能
computer.setCpu(new I7());
computer.getCpu().jiSuan();//i7主板的计算功能
}
}
public class Computer {
private String mainBoard; //主板
private Cpu cpu; // 相当于电脑预留了一个cpu接口,可以安装任意版本
public String getMainBoard() {
return mainBoard;
}
public void setMainBoard(String mainBoard) {
this.mainBoard = mainBoard;
}
public Cpu getCpu() {
return cpu;
}
public void setCpu(Cpu cpu) {
this.cpu = cpu;
}
@Override
public String toString() {
return "Computer{" +
"mainBoard='" + mainBoard + ''' +
", cpu=" + cpu +
'}';
}
}
public interface Cpu { void jiSuan(); // cpu的计算功能}class I3 implements Cpu{ @Override public void jiSuan() { System.out.println("I3 Cpu 的计算功能!"); }}class I5 implements Cpu{ @Override public void jiSuan() { System.out.println("I5 Cpu 的计算功能!"); }}class I7 implements Cpu{ @Override public void jiSuan() { System.out.println("I7 Cpu 的计算功能!"); }}
抽象类约束没有接口严格,抽象类中可以定义 构造方法、抽象方法、普通属性、普通方法、静态属性和静态方法
抽象方法一定要存在于抽象类中,但抽象类中不一定有抽象方法,也可以有具体的方法
抽象类不能创建对象(
Fruit fruit = new Fruit()
会报错)
public abstract class Fruit{ // 父类,此时父类也是抽象类
private String fruit;
public String getFruit();
public void setFruit(String fruit) {
this.fruit = fruit;
}
public abstract void eatFruit(); // 抽象方法
}
class Apple extends Fruit{ // 子类
private String color;
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
@Override
public void eatFruit() { // 必须要添加父类中的行为,否则会报错
System.out.println("吃"+color+"苹果!");
}
}
在方法区中会独立分配一块空间用来存放static修饰的数据,static修饰的东西都会存入其中,并且其中的数据是通用的
java中的关键字-----静态的
可以修饰属性和方法
static用在没有创建对象时调用方法/属性
静态成员变量
可以修饰全局变量,不能修饰局部变量
class test{ public static String name = "码农"; // 可以修饰全局变量(类变量) public void Do{ static String name2 = "码羊"; // 报错,不能修饰局部变量 } }
静态方法
可以使用类名.方法名调用
static
不能修饰 get方法、set方法、构造方法、抽象方法、类同一个类中调用类方法,可以省略类名
public class Circle implements Shape {
private static Double PI = 3.14; // 静态成员变量
privatE int r; // 非静态成员变量
// 静态方法
public static void area2(){
// 2*PI*r; // 报错,因为此为静态方法,而r为非静态成员变量
}
@Override
public void area() {
System.out.println(PI*r*r);
}
@Override
public void perimeter() {
System.out.println("计算Circle的周长");
}
}
静态代码快
用于类的初始化操作,进而提示程序性能
静态代码块随着类的加载而执行,因此,很多时候会将 只需要 执行一次的初始化操作放在static代码块中进行
public class StaicBlock {
static{
System.out.println("I'm A static code block");
}
}
最后的,最终的
可以修饰类、属性(全局变量和局部变量)、方法
final修饰类时
一旦修饰,表示此类不能被继承
成员变量可以根据需要设定为final
注意:final中的所有成员方法会隐式的指定为final方法
final修饰方法时
修饰方法时,表示此方法不能被子类重写
只有在明确不希望此方法被子类重写时才会将其设定为final
final修饰变量时
final没有优先分配的功能,所以必须对其进行赋值(可以使用构造代码块对其进行赋值,因为构造代码块会在构造方法前执行,且调用几次构造方法,便加载几次构造代码块)
修饰基本数据类型
表示数据类型的值 不能 被改变
public class Circle implements Shape {
private static Double PI = 3.14;
private static final Double PII = 3.14;
public static void main(String[] args) {
PI = 4.5; // 可以正常修改
// PII = 3.5; // 报错
}
}
修饰引用数据类型时
表示对其初始化后便 不能 在指向另一个对象
public class Test {
public static void main(String[] args) {
final Fruit fruit = new Fruit();
fruit.setFruit("苹果");
fruit = null; // 报错:CAnnot assign a value to final variable 'fruit'
}
}
class Fruit{
private String fruit;
public String getFruit() {
return fruit;
}
public void setFruit(String fruit) {
this.fruit = fruit;
}
}
以上是大佬教程为你收集整理的「Java基础」六、面向对象 进阶全部内容,希望文章能够帮你解决「Java基础」六、面向对象 进阶所遇到的程序开发问题。
如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。