⭐️前面的话⭐️
本篇文章带大家认识Java基础知识——包与继承,在Java当中一切皆可视为对象,而对象是由类所实例化出来的,将类组织起来那就是一个包,类与类之间是可以存在关联的,例如猫,狗,鸟等动物存在相同的行为或特征,我们把这些相同的行为与特征都集中起来构建成一个新的类,则猫,狗,鸟等动物都继承了该类。
📒博客主页:未见花闻的博客主页
🎉欢迎关注🔎点赞👍收藏⭐️留言📝
📌本文由未见花闻原创,CSDN首发!
📆首发时间:🌴2021年11月20日🌴
✉️坚持和努力一定能换来诗与远方!
💭参考书籍:📚《Java核心技术》,📚《Java编程思想》,📚《Effective Java》
💬参考在线编程网站:🌐牛客网🌐力扣
博主的码云gitee,平常博主写的程序代码都在里面。
博主的github,平常博主写的程序代码都在里面。
🙏作者水平很有限,如果发现错误,一定要及时告知作者哦!感谢感谢!
📌导航小助手📌
- 1.包
- 1.1概念
- 1.2类的组织
- 1.3导入包中的类
- 1.4静态导入
- 1.5包访问权限
- 2.继承
- 2.1什么是继承?
- 2.2类的继承
- 2.2.1继承的特征
- 2.2.2Java中继承的规则
- 2.3访问权限
- 2.4this与super区别
- 3.留给读者
1.包
1.1概念
Java 允许使用包( package )将类组织起来。借助于包可以方便地组织自己的代码,并将自己的代码与别人提供的代码库分开管理。
标准的 Java 类库分布在多个包中,包括 java.lang、java.util 和java.net 等。标准的 Java包具有一个层次结构。如同硬盘的目录嵌套一样,也可以使用嵌套层次组织包。所有标准的Java 包都处于java 和 javax 包层次中。
使用包的主要原因是确保类名的唯一性。 假如两个程序员不约而同地建立了Employee类。只要将这些类放置在不同的包中, 就不会产生冲突。事实上,为了保证包名的绝对唯一性, Sun 公司建议将公司的因特网域名(这显然是独一无二的) 以逆序的形式作为包名,并且对于不同的项目使用不同的子包。例如, weijianhuawen.com
是一个的域名。逆序形式为 com.weijianhuawen
。这个包还可以被进一步地划分成子包, 如 com.weijianhuawen.corejava
。
✨从编译器的角度来看, 嵌套的包之间没有任何关系。例如,java.util
包与java.util.jar
包毫无关系。每一个都拥有独立的类集合。
1.2类的组织
对类进行组织是由关键字package
来设置类所在的包路径。
package 路径;
package com.csdn.test;
⭐️规则:
- 在
.java
文件最上面加上package
语句指定该文件的代码所在的包。 - 包名尽量指定成唯一的名字,一般采用公司或单位的域名的颠倒形式。(如csdn.com,则包名com.csdn…)
- 包名要与路径相统一,如一个包名为
com.csdn.test
,则它所对应的路径为com/csdn/test
。 - 如果没有package包,则这些类会被放在一个默认包中。
包的创建:
不过在创建包前要注意设置一下编译器,这样编译器才能自动将你所写的包名根据.
分开自动生成路径,否则有可能出现包名为com.csdn.test
。
包创建好后,创建一个类,编译器自动会生成语句package指定当前类所在的包。
1.3导入包中的类
在一个类中我们经常需要使用Java内置的一些方法,这个时候往往需要导包,比如以字符串输出数组的方法toString
,我们需要导入java.util
包中的Arrays
类。
最原始的方法就是将类的具体路径写出来,再调用方法。
package com.csdn.test;
public class Package {
public static void main(String[] args) {
int[] arr = {1,2,3,4,5,6,7,8,9};
String s = java.util.Arrays.toString(arr);
System.out.println(s);
}
}
除此之外,有一个关键字import
能够导入一个包中具体的类。
package com.csdn.test;
import java.util.Arrays;//导入java.util包中的Arrays类
public class Package {
public static void main(String[] args) {
int[] arr = {1,2,3,4,5,6,7,8,9};
System.out.println(Arrays.toString(arr));
}
}
Arrays是直接点出toString
方法说明该方法是静态的。
除了import java.util.Arrays
导入包中的类,还可以使用import java.util.*
,这个语句会导入java.util
包中所有的类,但是不是直接将这个包中所有类全部导入,而是用到哪一个类就导入哪一个类。比如说只用Arrays
类,实际上只会导入Arrays
类,而这个*
可以理解为通配符。
但是使用*
导入类可能会存在一个问题,就是你导入两个或多个包,其中里面有两个包有同名的类,这个时候就会报错,因为编译器不知道你究竟需要导哪一个类。比如Date
类,
这个时候要么写全路径访问,要么导包时具体导入所需要的那一个类。
如果你要得到一个时间戳,则导入包时语句需改为:
import java.util.Date;
import java.sql.*;
package com.csdn.test;
import java.util.Date;
import java.sql.*;
public class Import {
public static void main(String[] args) {
Date date = new Date();
//获取时间戳
System.out.println(date.getTime());
}
}
如果不想改import语句,这需要写出类的全路径创建对象。
package com.csdn.test;
import java.util.*;
import java.sql.*;
public class Import {
public static void main(String[] args) {
java.util.Date date = new java.util.Date();
//获取时间戳
System.out.println(date.getTime());
}
}
因为时间一直在变,所以时间戳也一直在变,所以不同时间运行程序结果是不同的。
如果导入类的类名与所在类类名相同,请把类名修改,否则会报错。
//被导入的类
package com.csdn.test;
public class Package {
public int add(int a, int b) {
return a + b;
}
}
import com.csdn.test.Package;
public class Package2 {
public static void main(String[] args) {
Package p = new Package();
int sum = p.add(2,3);
System.out.println(sum);
}
}
1.4静态导入
使用import static
可以导入包中静态的方法或字段。
比如我们最常使用的打印方法:
package com.csdn.test;
import static java.lang.System.*;
public class Test {
public static void main(String[] args) {
String name = "未见花闻";
out.println(name);
}
}
还有数学运算方法Math
包,里面的方法也是静态的。
package com.csdn.test;
import static java.lang.Math.*;
public class Test {
public static void main(String[] args) {
int a =2;
double b = pow(a, 3);
System.out.println(b);
System.out.println(abs(-999));
System.out.println(min(1, 5));
System.out.println(max(122, 867));
}
}
注 意 : j a v a . l a n g : 系 统 常 用 基 础 类 ( S t r i n g 、 O b j e c t ) , 此 包 从 J D K 1.1 后 自 动 导 入 。 注意: java.lang:系统常用基础类(String、Object),此包从JDK1.1后自动导入。 注意:java.lang:系统常用基础类(String、Object),此包从JDK1.1后自动导入。
1.5包访问权限
前面我们已经了解了 p u b l i c 和 p r i v a t e public和private public和private这两个关键字分别表示公共与私有。但是一个类中的成员我们既没有说明public也没有说明private,没有任何访问权限的关键字修饰,则表示默认权限,即包访问权限,就是在同一个包内能够访问,不同包之间是不能访问的。
package com.csdn;
public class Demo2 {
int val = 10;
}
在包外访问不到这个val:
包内访问:
package com.csdn;
public class Demo2 {
int val = 10;
public static void main(String[] args) {
Demo2 d = new Demo2();
System.out.println(d.val);
}
}
2.继承
2.1什么是继承?
先来看一段代码:
class Dog {
public String name;
public int age;
public Dog(String name, int age) {
this.name = name;
this.age = age;
}
public void eat() {
System.out.println(name + "在吃饭!");
}
public void run() {
System.out.println(name + "正在跑!");
}
}
class Bird {
public String name;
public int age;
public Bird(String name, int age) {
this.name = name;
this.age = age;
}
public void eat() {
System.out.println(name + "正在吃饭!");
}
public void fly() {
System.out.println(name + "正在飞!");
}
}
public class Test1 {
public static void main(String[] args) {
Dog dog = new Dog("小狗", 18);
dog.run();
dog.eat();
Bird bird = new Bird("小鸟", 19);
bird.fly();
bird.eat();
}
}
我定义了两个类,一个是
D
o
g
Dog
Dog,另一个是
B
i
r
d
Bird
Bird,里面存放了两种动物的行为与特征,但是我们发现它们有不少共同点,比如它们都有名字,年龄,都会吃饭,这是所有动物都有的特征与行为,所以我们不妨将这些共同的特征封装成一个类
A
n
i
m
a
l
Animal
Animal,然后在定义
D
o
g
,
B
i
r
d
Dog,Bird
Dog,Bird类的时候后面加上extends Animal
,这代表
D
o
g
,
B
i
r
d
Dog,Bird
Dog,Bird类继承了类
A
n
i
m
a
l
Animal
Animal,
D
o
g
,
B
i
r
d
Dog,Bird
Dog,Bird类中不需要定义名字,年龄字段,吃饭的方法,就能使用这些成员变量和方法,这就叫做
继
承
继承
继承。其中
D
o
g
,
B
i
r
d
Dog,Bird
Dog,Bird为子类,
A
n
i
m
a
l
Animal
Animal类为父类。所谓继承,就是子类继承父类的字段和方法,private
修饰的成员子类不能继承,或者说能继承,但是子类不能访问它,因为private
的属性就是只能在类中进行访问,子类与父类不是同一个类,所以子类访问不了父类private
修饰的成员。
class Animal {
public String name;
public int age;
public void eat() {
System.out.println(name + "在吃饭!");
}
}
class Dog extends Animal{
public Dog(String name, int age) {
this.name = name;
this.age = age;
}
public void run() {
System.out.println(name + "正在跑!");
}
}
class Bird extends Animal{
public Bird(String name, int age) {
this.name = name;
this.age = age;
}
public void fly() {
System.out.println(name + "正在飞!");
}
}
public class Test1 {
public static void main(String[] args) {
Dog dog = new Dog("小狗", 18);
dog.run();
dog.eat();
Bird bird = new Bird("小鸟", 19);
bird.fly();
bird.eat();
}
}
2.2类的继承
前面用了一个实例引出了什么是继承,接下来我们来讨论一下继承的一些细节。
2.2.1继承的特征
继承的特征指的是对共性的抽取 ,使用 e x t e n d s extends extends关键字进行处理,能够对代码进行重复使用。
2.2.2Java中继承的规则
✨基本规则:
- Java中的继承是单继承,不能同时继承多个类(两个或两个以上),但是可以连续继承。
- 子类构造时,需 先 对父类帮助进行构造。
- s u p e r super super关键字表示父类对象的引用(不能出现在静态方法中),可以使用该关键字调用父类的构造方法与成员。
⭐️关于 s u p e r super super:
- s u p e r ( ) super() super(),调用父类的构造方法。
- s u p e r . f u n c ( ) super.func() super.func(),调用父类的成员方法。
- s u p e r . d a t a super.data super.data,访问父类的成员变量。
- s u p e r ( ) super() super()在子类构造方法没有写,默认调用父类无参构造。
细心的同学已经发现了,上面所写的代码,并没有发现子类帮助父类进行构造,但是程序依然可以正常运行,其实当没有定义任何构造方法时,编译器会自动生成一个不带参数的构造方法,父类中没有定义构造方法,所以父类会生成一个不带参数的构造方法,子类的构造方法如果没有帮助父类调用构造方法时,相当于会自动生成不带参数的 s u p e r ( ) super() super(),所以程序依然可以正常运行。相当于下面的代码:
class Animal {
public String name;
public int age;
public void eat() {
System.out.println(name + "在吃饭!");
}
}
class Dog extends Animal{
public Dog(String name, int age) {
super();
this.name = name;
this.age = age;
}
public void run() {
System.out.println(name + "正在跑!");
}
}
class Bird extends Animal{
public Bird(String name, int age) {
super();
this.name = name;
this.age = age;
}
public void fly() {
System.out.println(name + "正在飞!");
}
}
如果在父类中定义了一个带参数的构造方法,如果子类没有调用父类的构造方法,则会报错。
我们再来看一段代码:
class Animal {
public String name;
public int age;
public Animal(String name, int age) {
this.name = name;
this.age = age;
}
public void eat() {
System.out.println(name + "在吃饭!");
}
}
class Dog extends Animal{
public Dog(String name, int age) {
super("动物", 1);
this.name = name;
this.age = age;
}
public void run() {
System.out.println(name + "正在跑!");
}
public void fatherClass() {
System.out.println(super.name + super.age);
}
}
public class Test1 {
public static void main(String[] args) {
Dog dog = new Dog("小狗", 18);
dog.fatherClass();
}
}
✨这个程序会输出什么呢?
A
.
小
狗
18
A.小狗18
A.小狗18
B
.
动
物
1
B.动物1
B.动物1
你们觉得是哪个选项呢?我们了看看输出结果:
答案是A。为什么呢?首先帮助父类进行构造name = "动物" age = 1
,然后子类在构造name = "小狗" age = 18
,因为子类中没有name
age
,所以两者访问的都是父类对象的name
age
,所以输出小狗18。
当然如果子类中有name
age
,则会输出动物1。
class Animal {
public String name;
public int age;
public Animal(String name, int age) {
this.age = age;
this.name = name;
}
public void eat() {
System.out.println(name + "在吃饭!");
}
}
class Dog extends Animal {
public String name;
public int age;
public Dog(String name, int age) {
super("动物", 1);
this.name = name;
this.age = age;
}
public void run() {
System.out.println(name + "正在跑!");
}
public void fatherClass() {
System.out.println(super.name + super.age);
}
}
public class Test2 {
public static void main(String[] args) {
Dog dog = new Dog("小狗", 18);
dog.fatherClass();
}
}
2.3访问权限
除了public, private, default(包访问权限),还有一个protected访问权限关键字,范围是在default的基础是加上父子类。
我们希望类要尽量做到 “封装”, 即隐藏内部实现细节, 只暴露出 必要 的信息给类的调用者.因此我们在使用的时候应该尽可能的使用 比较严格 的访问权限. 例如如果一个方法能用 private, 就尽量不要用public.
另外, 还有一种 简单粗暴 的做法: 将所有的字段设为 private, 将所有的方法设为 public. 不过这种方式属于是对访问权限的滥用, 还是更希望同学们能写代码的时候认真思考, 该类提供的字段方法到底给 “谁” 使用(是类内部自己用, 还是类的调用者使用, 还是子类使用).
✨如果一个类不想被继承可以使用关键字final
修饰类。
final
修饰字段(变量),则变量只能初始化赋值一次,不能修改,相当于常量。
final
修饰方法,则方法不能重写(下一篇博客详细介绍)。
2.4this与super区别
✨super来引用父类对象,用this来引用当前对象。
⭐️相同点:
- 均可以调用构造方法,但是两者不能同时出现在同一构造方法。
- 调用某构造方法时必须放在另一个构造方法第一行。
- 都不能放在静态方法中使用。
⭐️不同点:
- 引用对象不同。
- super()从子类中调用父类的构造方法,this()调用当前类的构造方法。
3.留给读者
下面代码输出什么?
class Animal {
public String name;
public int age;
public Animal(String name, int age) {
this.name = name;
this.age = age;
}
public void eat() {
System.out.println(name + "在吃饭!");
}
}
class Dog extends Animal{
public Dog(String name, int age) {
super("动物", 1);
this.name = name;
this.age = age;
}
public void run() {
System.out.println(name + "正在跑!");
}
public void fatherClass() {
System.out.print(super.name + super.age);
}
}
class Bird extends Animal{
public Bird(String name, int age) {
super("动物", 1);
this.name = name;
this.age = age;
}
public void fly() {
System.out.println(name + "正在飞!");
}
public void fatherClass() {
System.out.print(super.name + super.age);
}
}
public class Test1 {
public static void main(String[] args) {
Dog dog = new Dog("小狗", 18);
Bird bird = new Bird("小鸟", 19);
dog.fatherClass();
bird.fatherClass();
}
}
A
.
小
狗
18
小
鸟
19
A.小狗18小鸟19
A.小狗18小鸟19
B
.
小
鸟
19
小
鸟
19
B.小鸟19小鸟19
B.小鸟19小鸟19
C
.
小
狗
18
小
狗
18
C.小狗18小狗18
C.小狗18小狗18
D
.
小
狗
18
动
物
1
D.小狗18动物1
D.小狗18动物1
答案找博主,或者下篇博文见!