abstract类中不可以有private的成员_别再说你不懂java面向对象了,阿里P7大佬一次性给你讲的明明白白
前言
面向对象在百度百科中是这样解释的:“面向对象是一种对现实世界理解和抽象的方法,是计算机编程技术发展到一定阶段后的产物”。说的好像很流弊的样子,看看就行。
包的认识
1.1:包的概念包是组织、整合类的一种方式其目的在于保证使用类的唯一性(同一个包中,里面所包含的类名是唯一的)比如在包A中定义了一个Test类,在包B中也定义了一个Test类,那么当使用A中的Test类时便导入包A调用A中的Test类(A.Test),以此保证类的唯一性。
1.2:导入包中的类Java中有很多现成的包供我们使用,使用这些包的方式有两种
public class TestDemo { public static void main(String[] args) { java.util.Date time = new java.util.Date(); //使用 util 包中的Date类创建一个对象 System.out.println(time.getTime()); //调用该对象的 getTime 方法,获得一个毫秒级别的时间戳 }}
上述代码中,util 就是一个包,Date就是该包中的一个类,使用时用 java.包名.类名 使用
import java.util.Date;public class TestDemo { public static void main(String[] args) { Date time = new Date(); System.out.println(time.getTime()); }
第一个代码每次使用类时都要加包的前缀,太过麻烦,因此还可使用第二种方式,在代码最开头使用 import 关键字导入需要的包,这样就可以像使用自己定义的类一样,直接用类名创建对象当同时需要同一个包中的多个类是,可以用 import.java.包名.* 的方式导入包,这样就可以使用该包下的所有类(但建议不要这么使用,否则当导入多个包时还是会出现类名重复的现象)。
1.3:静态导入包中除了类的普通方法外,还有一些静态方法,使用这些方法时,可以使用 import static 的方式导入包中的静态字段和方法,无需创建对象直接使用
import static java.lang.Math.*;public class TestDemo { public static void main(String[] args) { double x = 10.5; double y = 3.0; double result = sqrt(pow(x,y)+pow(x,y)); System.out.println(result); }
1.4:自定义类放入包中基本规则
- 在文件的最上方加一个 package 语句指定该代码在哪个包中
- 包名尽量指定成唯一名字,防止多文件间冲突
- 包名和代码路径相匹配
- 如果一个类没有 package 语句,则该类会被放到默认包中
1.5:包的访问权限控制如果某个成员不包含 public 和 private 关键字,此时这个成员可以被包中的其他类使用,但不能在包外部类中使用
1.6:常见的系统包1、java.lang:系统常用基础类(String,Object),jdk1.1以后自动导入2、java.lang.reflect: java 反射编程包3、java.net:进行网络编程开发包4、java.sql:进行数据库开发的支持包。5、java.util:是java提供的工具程序包。(集合类等)6、java.io:I/O编程开发包。
继承
2.1 概念:当创建多个类时发现这些类之间存在一定的关联关系,则可以创建一个父类拥有这些类的相同属性和方法,让这些类继承与父类,来提高效率,达到代码重用的效果。此时被继承的类我们成为 父类、基类或者超类,而继承的类我们称为子类或者派生类,子类会继承父类除构造方法外的其他所有东西。2.2 语法规则:class 子类 extend 父类{
}
- 子类使用 extend 关键字继承父类
- Java中一个子类只能继承一个父类
- 子类会继承父类的所有 public 的字段和方法
- 对于父类的 private 的字段和方法,子类无法访问
- 子类实例中也包含父类实例,可使用 super 关键字得到父类的引用
class Animal{ public String name;//父类的name必须为 public 否则子类将无法访问 public Animal(String name) { this.name = name; } public void eat(String food){ System.out.println(this.name+"吃"+food); }}class Dog extends Animal{ public Dog(String name){ super(name); }}class Bird extends Animal{ public Bird(String name){ super(name); } public void fly(){ System.out.println(this.name+"正在飞"); }}public class TestDemo { public static void main(String[] args) { Dog dog = new Dog("旺旺"); dog.eat("骨头"); Bird bird = new Bird("啾啾"); bird.eat("米粒"); bird.fly(); }
2.3、protected关键字上述代码中,如果将父类的 name 设为 private子类将无法访问,但设为 public 又违背了封装的规则,此时就需要用到 protect 关键字
- 对于其他类的调用者来说,被 protect 修饰的字段和方法是不能被访问的
- 但对于 该类的子类 和 同一个包下的其他类 来说,被 protect 修饰的字段和方法是可以被访问的
小结:Java中对字段和方法共有四种访问权限
- private:只能在类内部访问,内外部一律不行
- 默认:在类内部能访问,同一个包中的类也可以访问
- protect:在类内部能访问,且在其子类和同一个包中的类也可以访问
- public:类内部和类的调用者都能访问
2.4、final关键字final 可以修饰一个变量或者字段,用来表示常量final 也恶意修饰一个类,用来表现该类不能被继承组合:即一个类中对另一个类的嵌套,在一个类中实例另一个类,达到代码重用的效果
多态
3.1、向上转型:如上代码,创建一个 Bird 的对象可以写成
Bird bird = new Bird();
也可以写成
Bird bird = new Bird();Animal bird2 = bird;Animal bird3 = new Bird();
此时bird2、bird3是一个父类(Animal)的引用,指向子类(bird)的实例,这称为向上转型。向上转型发生的时机:
- 直接赋值(即上述代码演示)
- 方法传参
- 方法返回
方法传参:
public static void main(String[] args) { Bird bird = new Bird("啾啾"); feed(bird);}public static void feed(Animal animal){ animal.eat("谷子");}
此时形参的类型是 Animal(父类) ,实际上是对应到 Bird(子类)的实例
方法返回:
public static void main(String[] args) { findAnimal().eat("谷子");}public static Animal findAnimal(){ Bird bird = new Bird("啾啾"); return bird;}
方法 findAnimal 返回值是 Animal 的一个引用,但实际指向 Bird 的一个实例
3.2:动态绑定子类和父类出现同名方法时发生
class Animal{ public String name; public Animal(String name) { this.name = name; } public void eat(String food){ System.out.println("我是一只小动物"); System.out.println(this.name+"正在吃"+food); }}class Bird extends Animal{ public Bird(String name){ super(name); } public void eat(String food){ System.out.println("我是一只小鸟"); System.out.println(this.name+"正在吃"+food); } public void fly(){ System.out.println(this.name+"正在飞"); }}public class TestDemo { public static void main(String[] args) { Animal animal1 = new Animal("动物"); Animal animal2 = new Bird("小鸟"); animal1.eat("谷子"); animal2.eat("谷子"); }
执行以上代码我们发现:
- animal1 和 animal2 虽然都是 Animal 类型的引用,但animal1指向 Animal 实例的对象,animal2指向 Bird 实例的对象
- 对 animal1 和 animal2 分别调用eat方法,发现 animal1 调用的是父类的方法,animal2 调用的是子类的方法
在Java中,调用某个方法,究竟执行哪段代码(是父类方法还是子类),取决于看这个引用指向的对象是父类对象还是子类对象,这个过程是在运行时才决定的,因此成为动态绑定父类引用,引用子类对象时,只能访问自己特有的,不能访问子类独有的
3.3、重写对于上述代码,父类和子类的eat方法来说,就构成了重写重写的注意事项:
- 普通方法可以重写,static 修饰的方法不能重写
- 重写中子类的访问权限不能低于父类的访问权限
- 重写和重载不同
重写和重载的区别
1.要求不同重载:a.方法名相同 b.参数列表不同 c.返回值不做要求重写:a.方法名相同 b.参数列表相同(参数类型和个数) c.返回值也要相同2.范围不同重载:同一个类中重写:继承关系,不同类中3.限制重载:无限制重写:子类中重写的方法访问权限不能低于父类的访问权限
3.4、理解多态
class Shape { public void draw(){ }}class Circle extends Shape{ public void draw(){ System.out.println("画一个圆圈○"); }}class Rectangle extends Shape{ public void draw(){ System.out.println("画一个矩形□"); }}class Triangle extends Shape{ public void draw(){ System.out.println("画一个三角△"); }}//================================================//================================================public class TestDemo { public static void main(String[] args) { Shape shape1 = new Circle(); Shape shape2 = new Rectangle(); Shape shape3 = new Triangle(); drawMap(shape1); drawMap(shape2); drawMap(shape3); } public static void drawMap(Shape shape){ shape.draw(); }
以上代码,分割线以上是由类的实现者编写的,分割线以下是由类的调用者编写的当调用者编写drawMap方法的时候(参数类型为父类Shape),并不关心当前shape引用指向哪个类型的实例,此时shape调用的draw方法只取决于shape指向的哪个类型的实例,以实现不同的表现形式,这种思想叫做多态。
3.5、向下转型父类引用,引用子类对象称为向上转型;子类引用,引用父类对象称为向下转型。
class Animal{ public String name; public Animal(String name) { this.name = name; } public void eat(String food){ System.out.println("我是一只小动物"); System.out.println(this.name+"正在吃"+food); }}ass Bird extends Animal{ public Bird(String name){ super(name); } public void eat(String food){ System.out.println("我是一只小鸟"); System.out.println(this.name+"正在吃"+food); } public void fly(){ System.out.println(this.name+"正在飞"); }} public class TestDemo { public static void main(String[] args) { Animal animal = new Bird("啾啾"); animal.eat("谷子"); animal.fly();//执行该行代码时,会报错误 }
编译过程中 animal 的类型时 Animal ,编译器编译时根据类型只知道 animal 中只有一个eat方法,找不到fly方法
- 编译器检查存在哪些方法时候,看的是 Animal 类型
- 执行时究竟执行父类方法还是子类方法,看的是 Bird 类型
但很多时候为了让向下转型更安全,需要判断一下 animal 是否指向 Bird 的引用,使用instanceof 关键字判断
Animal animal = new Cat("小猫");if (animal instanceof Bird) {Bird bird = (Bird)animal;bird.fly();}
3.6、super关键字当在子类内部要调用父类方法时,就要用到 super 关键字super 表示获取到父类实例的引用,其有两种常用方法
一、使用 super 来调用父类的构造方法,super(参数)
public Bird(String name){ super(name);}
二、使用 super 来调用父类的普通方法,super.方法名(参数)
class Bird extends Animal{ public Bird(String name){ super(name); } public void eat(String food){ super.eat(food); System.out.println("我是一只小鸟"); System.out.println(this.name+"正在吃"+food); }}
上述代码中个,如果直接调用eat方法,则被编译器认为是调用子类的方法(同递归),想要调用父类方法则需要使用 super 关键字
this和super的区别:
1、概念this:访问本类的属性和方法super:访问父类的属性和方法2、查找范围this:先查找本类,子类没有再调用父类super:不查找本类,直接调用父类3、特殊this:表示当前对象的引用super:表现父类对象的引用
多态存在的意义就在于,让调用者不必关注对象的具体类型,降低用户的使用成本
4、抽象类
4.1语法规则类似于之前代码的父类 Shape 中的draw方法,其中并没有实际工作,而由其子类重新该方法实现,那么像这种没有实际工作的方法我们就可以用 abstract 关键字修饰把它设计成一个抽象方法,而包含抽象方法的类我们就称为抽象类
abstract class Shape { abstract public void draw();}
- 在draw方法前加一个 abstract 修饰表示该方法是抽象方法,抽象方法没有方法体
- 对于包含抽象方法的类,class 前必须加一个 abstract 关键字表示是抽象类
注意事项:
- 抽象类不能直接实例
- 抽象方法的访问权限不能是private
- 抽象类中可以包含其他非抽象方法,也可以包含字段,和普通方法一样,可以被重新可以被调用
4.2抽象类的作用抽象类的意义在于为了被继承抽象类本身不能实例化,想要使用,必须创建该抽象类的子类,在子类中重写抽象方法使用抽象类相当于多了一重编译器的检验(对于抽象了来说,如果继承的子类不重写父类的抽象方法,则会报错)
5、接口
接口是比抽象类还抽象,接口只包含抽象方法,其字段也只能包含静态常量
interface IShape{ abstract public void draw();}class Circle implements Shape{ @Override public void draw() { System.out.println(); }}
- 用 interface 定义一个接口
- 接口中的方法只能是抽象方法,所以可以省略 abstract
- 并且接口中的方法只能是 public ,所以可以省略
- Circle 用 implement 来实现接口
- 在调用的时候同样可以创建一个接口的引用,对应到一个子类的实例
- 接口不能被单独实例化
在Java中一个类只能继承一个父类,但同时可以实现多个接口
class Animal{ public String name; public Animal(String name){ this.name = name; }}interface IFlying{ void fly();}interface IRunning{ void run();}interface ISwimming{ void swim();}class Dog extends Animal implements IRunning{ public Dog(String name){ super(name); } @Override public void run() { System.out.println(this.name+"正在跑步"); }}class Frog extends Animal implements IRunning,ISwimming{ public Frog(String name){ super(name); } @Override public void run() { System.out.println(this.name+"正在跑步"); } @Override public void swim() { System.out.println(this.name+"正在游泳"); }}class Duck extends Animal implements IRunning,ISwimming,IFlying{ public Duck(String name){ super(name); } @Override public void fly() { System.out.println(this.name+"正在飞"); } @Override public void run() { System.out.println(this.name+"正在游泳"); } @Override public void swim() { System.out.println(this.name+"正在游泳"); }}public class TestDemo { public static void main(String[] args) { Dog dog = new Dog("汪汪"); Frog frog = new Frog("呱呱"); Duck duck = new Duck("嘎嘎"); dog.run(); frog.run(); frog.swim(); duck.fly(); duck.run(); }}
接口使用实例——给对象数组排序创建一个学生类
class Students implements Comparable{ private String name; private int score; public Students(String name, int score) { this.name = name; this.score = score; } @Override public String toString() { return "Students{" + "name='" + name + ''' + ", score=" + score + '}'; } @Override public int compareTo(Object o) { Students s = (Students)o; if(s.score > ((Students) o).score){ return 1; }else if(s.score == ((Students) o).score){ return 0; }else{ return -1; } }}
在 sort 方法中会自动调用 compareTo 方法.compareTo 的参数是 Object,其实传入的就是Students类型的对象,然后比较当前对象和参数对象的大小关系
接口间的承接一个接口可以承接另一个接口,达到复用效果,使用 extends 关键字接口间承接相当于把多个接口凭借在一起
Clonable 接口和深拷贝Object 类中存在一个 clone 方法,调用这个方法可以创建一个对象的“拷贝”,但是想要合法的调用clone方法,必须先要实现 Clonable 接口,否则就会抛出 CloneNotSupportedException 异常
class Person implements Cloneable{ public String name; public Person(String name) { this.name = name; } @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } @Override public String toString() { return "Person{" + "name='" + name + ''' + '}'; }}public class TestDemo { public static void main(String[] args) throws CloneNotSupportedException { Person person1 = new Person("小明"); Person person2 = (Person) person1.clone(); person2.name = "小红"; System.out.println(person1); System.out.println(person2); }}
如下代码即深拷贝:
class Money implements Cloneable{ public int m=10; @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); }}class Person implements Cloneable{ public String name; public Money money ; public Person(String name) { this.name = name; this.money = new Money(); } @Override protected Object clone() throws CloneNotSupportedException { Person person = (Person) super.clone(); person.money = (Money) this.money.clone(); return person; } @Override public String toString() { return "Person{" + "name='" + name + ''' + ", money=" + money.m + '}'; }}public class TestDemo { public static void main(String[] args) throws CloneNotSupportedException { Person person1 = new Person("小明"); Person person2 = (Person) person1.clone(); person2.name = "小红"; person2.money.m = 15; System.out.println(person1); System.out.println(person2); }}
总结
- 抽象类和接口都是Java中多态的常见使用方法,但两者又有区别
最核心区别:抽象类可以包含普通方法和普通字段,可以被子类直接使用,而接口中只有抽象方法,实现该接口的类必须重写所有抽象方法
最后
感谢你看到这里,看完有什么的不懂的可以在评论区问我,觉得文章对你有帮助的话记得给我点个赞,每天都会分享java相关技术文章或行业资讯,欢迎大家关注和转发文章!
abstract类中不可以有private的成员_别再说你不懂java面向对象了,阿里P7大佬一次性给你讲的明明白白相关推荐
- abstract类中不可以有private的成员_我要告诉你:java接口中可以定义private私有方法...
在传统的Java编程中,被广为人知的一个知识点是:java Interface接口中不能定义private私有方法.只允许我们定义public访问权限的方法.抽象方法或静态方法.但是从Java 9 开 ...
- abstract类中不可以有private的成员_C++类成员的三种访问权限:public/protected/private...
1.访问限定符 C++ 通过 public.protected.private 三个关键字来控制成员变量和成员函数的访问权限(也称为可见性),分别表示:公有的.受保护的.私有的. class 2.访问 ...
- abstract类中不可以有private的成员_C++ 类:声明成员函数与实现
接上文... 16.3类的成员 2.成员函数 1.构造函数 ... 2.拷贝构造函数 有了类的构造函数我们就可以创建类的实例了,下图中分别使用不同的构造函数一共创建了4个动物的对象,现在程序中就有4个 ...
- abstract类中不可以有private的成员_UML类图还不懂?来看看这版乡村爱情类图,一把学会!
作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 一.码场心得 有个词叫内卷严重! 最开始听到这个词是有个小伙伴在我的一篇HashMap源码分析 ...
- abstract类中不可以有private的成员_C++中public、protected、private的区别
1.访问范围 private:只能由该类的成员函数.友元的成员函数访问,不能被其他类的成员函数访问,即使是该类的对象也不能直接访问 protected:可以被该类中的成员函数访问.子类中的成员函数访问 ...
- Spring MVC普通类或工具类中调用service报空空指针的解决办法(调用service报java.lang.NullPointerException)...
当我们在非Controller类中应用service的方法是会报空指针,如图: 这是因为Spring MVC普通类或工具类中调用service报空null的解决办法(调用service报java.la ...
- Spring MVC普通类或工具类中调用service报空空指针的解决办法(调用service报java.lang.NullPointerException)
当我们在非Controller类中应用service的方法是会报空指针,如图: 这是因为Spring MVC普通类或工具类中调用service报空null的解决办法(调用service报java.la ...
- php类如何变为静态调用,PHP类中静态方法如何调用非静态方法?_后端开发
php如何将字符串转成json_后端开发 php将字符串转成json的方法是:可以通过json_encode()函数来实现.json_encode()函数用于对变量进行JSON编码,该函数如果执行成功 ...
- java异常类中属于非检测异常的是_下列java语言的常用异常类中,属于检测异常的是()_学小易找答案...
[单选题]在Word 2010的编辑状态,对当前文档中的文字进行"字数统计"操作,应当使用的菜单是( ) [单选题]客运员领带统一,领带夹夹在衬衣的( )钮扣之间. [单选题]文件 ...
最新文章
- JButton 圆角_ProE、Creo在玩具轿车设计中的一个案例应用解析|轿车|玩具|圆角
- 三维家导入户型镜像怎么使用_UG虎钳三维建模教学,认真看仔细学习了!
- Android更新平台架构方案
- python数字信号处理应用中文pdf_人邮新书 Python数字信号处理应用 Python在DSP中应用教程 Python基础 Pytho...
- u-boot分析(八)----串口初始化
- Intel汇编语言程序设计学习笔记1
- virtual hust 2013.6.20 数论基础题目 E - Uniform Generator
- Ubuntu18.04安装OpenPCDet及配置spconv
- Ubuntu ROS Kinect2安装
- Ubuntu18.04 安装 nvidia2080Ti显卡驱动
- ROST反剽窃论文检测系统介绍
- 「算法介绍」如何设计最安全的加密机制
- JavaScript中使鼠标光标变为图片
- 【书记舞】MMD动作+镜头+配音下载
- 图解 JVM 内存结构
- LeetCode题解-6. ZigZag Conversion
- 处理猪舌须知小窍门-滋阴润燥好良方-菜椒滑猪舌
- OSChina 周一乱弹 —— 达叔撸猫图还是满满的少女心
- js仿百度文库文档上传页面的分类选择器_第二版
- R语言ROC分析、ROC曲线可视化及最佳阈值计算(threshold、cutoff)
热门文章
- linux查看密码配置文件,如何在Linux上查看和配置密码时效
- 查看MySQL句柄_mysql查询语句-handler
- python字符串前加r、f、u、l 的区别
- python如何批量发布数据并如何定时更换token
- 数据库本地的sa有个叉号_搞定sql数据库出错,做自己的大神!
- 为什么读写文件要有缓冲区?为什么要有输入输出缓冲区?
- ps -aux 和ps -elf 区别(查看进程)
- python matplotlib.figure.Figure.add_subplot()方法的使用
- 如何查看numpy库数组的:类型、数据类型、尺寸、形状、维度? (type、dtype、size、shape、ndim)
- mysql查阅建立的库_MySQL - 建库、建表、查询