这篇文章将为大家详细讲解有关Java中包和继承的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。
根据定义:包是组织类的一种方式
那么为什么要组织类呢?
简单来讲就是
保证类的唯一性
,就比如在以后的工作中,如果大家一起开发一个项目,大家可能在自己的代码中都写到了一个 Test 类,而如果出现了两个同名的类的话,就会冲突,导致代码不能编译通过。用一份代码理解下
import java.util.*; public class TestDemo{ public static void main(String[] args){ // 得到一个毫秒级的时间戳 Date date=new Date(); } }上面一份代码,导入了
util
包,并使用了其中的Date
类,目的是为了得到一个毫秒级的时间戳。而如果我们再导入一个sql
包import java.sql.*; import java.util.*; public class TestDemo{ public static void main(String[] args){ // 得到一个毫秒级的时间戳 Date date=new Date(); } }上述代码就会编译错误,会显示
Reference to 'Date' is ambiguous, both 'java.sql.Date' and 'java.util.Date' match
,即两个包中都有 Date 类,不知道该和哪个匹配。稍微修改下,确定该 Date 是和谁匹配就行,修改方式如java.util.Date date=new java.util.Date();或者修改这里也行
import java.sql.*; import java.util.Date;
Java
中已经提供了很多现成的类供我们使用,如上述代码中的 Date
类,还有我们经常使用的 Scanner
类、Arrays
类等等。
而这些类被放置在各个包中,比如 util 包中就有很多我们常用的类
虽说 Java
有这么多已经包装好的类供我们使用,但是并不是上面有的我们就可以直接使用。
其中 lang
包中的一些类可以直接使用,如 String
、Short
、Byte
、Float
等等(因为这些类会被自动导入),写一个代码理解下
public class TestDemo{ public static void main(String[] args){ // 输出 long 的最大值 System.out.println(Long.MAX_VALUE); } }
上述代码是输出 long
类型的最大值,其中使用了 Long 类的 Max_VALUE
方法。并且不需要手打导入 lang
包
而其它包使用时都需要手动导入,并且导入一般有以下几种方法
方法一: 直接在使用时,类前加包名,如
public class TestDemo{ public static void main(String[] args){ // 得到一个毫秒级的时间戳 java.util.Date date=new java.util.Date(); } }这种写法比较麻烦,不简洁
方法二: 使用 impot 语句直接导入某包中的某个类,如
import java.util.Date; public class TestDemo{ public static void main(String[] args){ // 得到一个毫秒级的时间戳 Date date=new Date(); } }注意:
导入包时也可以直接使用
**通配符 ***
,直接导入util
包中的所有,如import java.util.*;但是这个并不是直接将该包中的所有类全部导入,而是你用到哪个类就会导入哪个类。
但是会出现导入的两个包都使用通配符,并且两个包都包含同名类的话,则在使用时就会出现错误,如
import java.sql.*; import java.util.*; public class TestDemo{ public static void main(String[] args){ // 得到一个毫秒级的时间戳 Date date=new Date(); } }因此更推荐导入某个指定的类
方法三(下面会讲解,不常使用): 静态导入
了解到这里我们就会发现,Java 中的 import
和 C++ 中的 #include
差别很大,后者必须使用 #include
来引入其他文件内容,但是 Java 不需要。
其实之前讲方法那一章就提到过静态方法,而静态导入跟静态方法一样,都通过关键字 static 修饰,使用 import static 导入包。
而静态导入可以使我们不用写类名,这在某些时候会更加方便,例如
import static java.util.lang.Math.*; public class TestDemo{ public static void main(String[] args){ double x=3; double ans=pow(x,2); } }
其实 pow
方法就省略了类名 Math
既然理解了 Java 中的包,那么我们自己可以创建一个包吗?因为这样的话,我们就可以在和别人一起开发的时候,使用同一个类名了!
基本规则:
包中的文件最上方要加上一个 package
语句,来指定该代码在哪个包中
包名要和代码路径相匹配
如果一个类没有 package
语句,则会被放到一个默认的包中
包名需要全部小写,并尽量指定成唯一的名字(一般取名如下)
个人项目:pers.发起者名.项目名.模快名
团队项目:pers.团队名.项目名.模快名
公司项目:com.公司名.项目名.模快名
为了方便上述规则的理解,接下来让我来手动创建一个包吧!
创建及使用步骤:
右键 src ,点击new ,选择创建一个package
创建包名,包名全部小写
创建之后我们就可以看到这些,并且包名和代码的路径一致
点击 demo1,创建一个 Java 文件
大家发现没,我创建了一个叫
TestDemo
的类,而这个名字在 src 中已经有了。这就是包的作用!并且这个文件上面有package pers.dmw.demo1
; 指定了该代码的位置使用创建的类
当我们输入 Test 的时候,它出现了两个 TestDemo,下面哪个就是我们创建的类。按照我们以上所学的,先导入包,再使用这个类
完成啦!
之前学类时,我们学过 public
和 private
,其中被 public
修饰的成员在整个工程都可以使用,而被 private
修饰成员的则只能在自己的类中使用
而都不被这两者修饰的成员,则可以在这个包的其他类中使用,但是不能在其他包中使用
比如我们个人创建的包中定义两个类 TestDemo1
和 TestDemo2
,而 TestDemo
是其他包中的
其中 TestDemo2
代码如下
package pers.dmw.demo1; public class TestDemo2 { public int a=10; private int b=20; int c=30; }
Testdemo1
代码如下
package pers.dmw.demo1; public class TestDemo1 { public static void main(String[] args) { TestDemo2 testDemo2=new TestDemo2(); System.out.println(testDemo2.a); System.out.println(testDemo2.b); System.out.println(testDemo2.c); } }
其中 b 不能打印,因为 b 被 private
修饰,只能在自己的类中使用
TestDemo
代码如下
package pers.dmw.demo1; public class TestDemo { public static void main(String[] args) { TestDemo2 testDemo2=new TestDemo2(); System.out.println(testDemo2.a); System.out.println(testDemo2.b); System.out.println(testDemo2.c); } }
其中 b 和 c 都不能打印,b 是被 private 修饰的类,而 c 没有被修饰,只能在自己的包中使用
包大概的知识已经介绍完了,最后让我们来了解下那些常见的系统包吧!
java.lang:
系统常用基础类(String、Object
),此包从 JDK1.1 后自动导入。
java.lang.reflflect:
java 反射编程包
java.net:
进行网络编程开发包
java.sql:
进行数据库开发的支持包
java.util:
是 Java 提供的工具程序包
java.io:
I/O 编程开发包
我们知道面向对象的基本特征就是:继承、封装、多态
我们已经了解过封装了,接下来就开始学习继承
学习继承之前我们首先回忆一下类与对象,之前我举了一个洗衣服的例子,不记得的朋友可以去看看之前的文字Java 基础语法让你弄懂类和对象
而今天我再用一个谜语更好的帮大家去理解类和对象
谜语:
年纪不大,胡子一把。客人来啦,就喊妈妈(打一动物)
谜底:
诶!?先猜,谜底我已经放到本章的最后了,猜完的小伙伴可以到下面去验证哈
我们可以发现
谜语就是一种抽象
谜底就是一个具体
类就是一个事物的抽象
对象就是一个抽象的具体
回顾了类与对象之后,我们开始学习继承,那么继承是什么呢?
其实这里的继承和我们生活中的继承很类似,比如谁继承了长辈的产业。我们也可以用这样的比喻去写一个代码。
首先我们看一幅图
图片里有一只羊和一只狼,然后它们都属于动物对吧,那我们可以根据动物去写一个类
class Animal{ public String name; public int age; public void eat(){ System.out.println("我要睡觉啦!"); } public void bark(){ System.out.println("我要叫啦!"); } }
该类中,定义了动物的名字、年龄属性以及睡觉、叫的行为。我们再继续对狼和羊定义一个类
狼
class Wolf{ public String name; public int age; public void eat(){ System.out.println("我要睡觉啦!"); } public void bark(){ System.out.println("我要叫啦!"); } public void hunt(){ System.out.println("我要猎食啦!"); } }
羊
class Sheep{ public String name; public int age; public int cleatNum; public void eat(){ System.out.println("我要睡觉啦!"); } public void bark(){ System.out.println("我要叫啦!"); } }
我们发现,在羊和狼的类的定义时,由于它们都属于动物,所以动物的一些属性和行为它们都有,所以我们可以通过继承,将羊和狼的类的代码变得更加简介
狼
class Wolf extends Animal{ public void hunt(){ System.out.println("我要猎食啦!"); } }
羊
class Sheep extends Animal{ public int cleatNum; }
如上述代码中的 A extends B
就是继承。其中
A:叫做子类或者派生类
B:叫做父类、基类或者超类
当子类继承了父类之后,子类就拥有了父类的方法和属性
因此继承的意义就是
为了代码的重复使用
继承的思想就是
抽取共性,放到基类当中
extends
这里我们再更加详细的介绍继承的语法规则,以便于解决一些疑惑的地方
语法:
class 子类 extends 父类{ }
规则:
Java
中一个子类只能继承一个父类(C++/python
等语言支持多继承)
子类会继承父类的所有 public
的字段和方法
对于父类的 private
的字段和方法,子类无法访问(可以继承)
子类的实例中,也包含着父类的实例,可以使用 super
关键字得到父类实例的引用
注意:
由于 Java 当中只能单继承,为了解决这个问题,后面可以通过接口来实现类似于“多继承”的关系
那么上述关键字 super
是什么意思呢?首先我们看这样一段代码
class Animal{ public String name; public void eat(){ System.out.println(this.name + "要睡觉啦!"); } public void bark(){ System.out.println(this.name + "要叫啦!"); } } class Wolf extends Animal{ public void hunt(){ System.out.println(this.name + "要猎食啦!"); } } public class TestDemo{ public static void main(String[] args){ Wolf wolf=new Wolf(); wolf.name="灰太狼"; wolf.eat(); wolf.bark(); wolf.hunt(); } }
这就是一个简单的子类继承父类的使用。
我们知道创建一个对象分为两步:为对象分配内存和调用构造类。当我们没有定义构造方法时,系统会自动为我们构造一个无参的构造方法。
那如果我们在父类中主动的创建一个构造方法
class Animal{ public String name; public Animal(Stirng name){ this.name=name; } public void eat(){ System.out.println(this.name + "要睡觉啦!"); } public void bark(){ System.out.println(this.name + "要叫啦!"); } }
那么我们要记住:子类继承父类,需要先帮父类构造。那么怎么构造呢,就要用到 super
class Wolf extends Animal{ public Wolf(String name){ super(name); // 显示的调用父类的构造方法 } public void hunt(){ System.out.println(this.name + "我要猎食啦!"); } }
其中 super
就是调用父类的构造方法,这就满足子类继承父类之前,要先构造父类的构造方法
再具体理解下 super
:
super:表示当前对象的父类的引用(但这个说法不严谨,这是和 this 类比的结论)
super():调用父类的构造方法
super.父类属性:调用父类的属性
super.父类方法:调用父类的方法
注意:
当我们不主动创建构造方法时,但不是也有系统主动创建的构造方法吗?因为当我们不主动创建时,系统也主动使用了 super
super
不能和 this
一起使用,因为它们都要放在第一行
super
不能放在被 static
修饰的方法中使用,因为它依赖于对象
super
只会指向最直接的父类,不会指向父类的父类
我们对之前学的关键字 public
、private
、默认以及即将要学的关键字 protected
做一个比较,就可以得到下面的表格
num | 范围 | private | 默认(包访问权限) | protected | public |
---|---|---|---|---|---|
1 | 同一包中的同一类 | ✔ | ✔ | ✔ | ✔ |
2 | 同一包中的不同类 | ✔ | ✔ | ✔ | |
3 | 不同包中的子类 | ✔ | ✔ | ||
4 | 不同包中的非子类 | ✔ |
我们发现在上述代码中,我使用的继承时,父类代码的属性都是用 public
修饰的。这样子类就可以正常使用这些属性,但是这就违背了“封装”的思想。但是如果用 private
修饰,不同包的子类又不能访问
因此出现了一个关键字 protected
,使用它的话
对于不同包的非子类: protected
修饰的字段和方法是不能访问的
对于不同包的子类和同一包的其他类:protected
修饰的字段和方法是能访问的
学到这里,我们可以开始解决之前一些未提及的问题了:如果父类和子类都含有同一个参数,那调用时是使用哪个呢?我们来看下面的代码
class Base{ public int a=1; } class Derieve extends Base{ public int a=3; public void func(){ System.out.println(a); } } public class TestDemo{ public static void main(String[] args){ Derieve derieve=new Derieve(); derieve.func(); } } // 结果为:3
也就是说,调用时也是依靠了一个就近原则,默认为子类中的。那么调用时想调用父类该怎么办呢?这时我们就可以使用 super
来调用父类的属性。将 Derieve
类 改成这样即可
class Derieve extends Base{ public int a=3; public void func(){ System.out.println(super.a); } } // 结果为:1
至于方法同名的问题下章将讲解!
以上的继承关系都比较简单,如果关系变得更复杂时,如这个样子,我们该怎么办呢?
emmm,其实一般建议是不希望超过三层的继承关系的,如果继承层次太多了,就需要考虑重构代码。
而有时我们不知不觉就写了很多的继承关系,所以为了在语法上进行限制继承,就可以使用关键字 final
之前我们了解过 final
,它可以修饰一个变量或者字段,使其变成常量,不可以被修改,如
final int a=10; // a 为常量不可以被修改
而在这里,final
也能修饰类,此时被修饰的类就不能被继承了,被叫做密封类,如
final class A{ }
此时 A 就不能被继承了
final
也可以修饰方法,被修饰的方法叫做密封方法,至于此时 final
有什么作用,下章将会讲解!
上述重点讲解了继承相关的内容,而继承的意义就是:使代码可以重复使用
而组合也是一种表达类之间关系的方式,也能够达到代码重用的效果
顾名思义,组合就是将各种东西组合成一个东西。比如学习,学校就是由老师、学生、教学楼等等组合而成的,我们可以写一个代码
class Teacher{ // ... } class Student{ // ... } public class School{ public Teacher[] teachers; public Student[] students; }
上述代码就是将老师和学生的类封装成了对象,并且作为了另一个类的字段
关于“Java中包和继承的示例分析”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,使各位可以学到更多知识,如果觉得文章不错,请把它分享出去让更多的人看到。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。