文章目录
一、包
包是什么?
书包里装的是书,钱包里装的是钱,化妆包里装的是化妆品,而 Java 中的包里装的是各种各样的类
。
在 IDEA 中创建一个类通常的做法是在 src 下直接创造一个类,比如这个类叫 TestDemo ,此时,在这个包里名为 TestDemo 的 java 文件有且只能有一个。
在做一个大的工程项目时,如果大家都采取这样的创建类的方式,很难保证同事不和你一样写一个 TestDemo 类,当同一个包里面有两个类重名时,编译代码时就会出现错误。
为能够更好地组织类
,保证类的唯一性,Java 提供了包
机制,用于区别类名的命名空间。
当我们在 IDEA 中创建一个 TestDemo 类后,可以这么做,来看看这厮究竟搁哪地儿了。
综上所述,简而言之!包!说白了就是一装着类的文件夹!
1.1 把类从包里导进来
在此之前,我们其实已经使用过许多 Java 为我们准备的类,当需要使用时直接用 import
关键字将其导入即可。
📑代码示例一:
//方法一
import java.util.Arrays;
import java.util.Scanner;
//方法二
//import java.util.*;
public class TestDemo {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
//System.in 表示从键盘进行读入
int[] array = {1,2,3,4};
System.out.println(Arrays.toString(array));
}
}
💬代码解释:
- 想要使用
Scanner
和Arrays
这两个类,就需要用import
关键字将util
包下的Scanner
和Arrays
这两个类导入到程序当中,如果不导入,类就没有办法使用。- 方法一属于
单类型的导入
,即用哪个类就导入哪个类- 方法二属于
按需类型的导入
,*
表示的是通配符
包括 util 的所有的类,后程序中如果要用到这个包中的别的类都不需要再重新导入包了。实际上,真正导入的时候并不会导入所有的类
,而是用到哪个类就导入哪个类
,这也是 Java 的一大好处。
在众多的类中有这样的一种特殊的类,两个包中都有该类,例如 Date 类。
📑代码示例二:
import java.util.*;
import java.sql.*;
public class TestDemo {
public static void main(String[] args) {
//方法一
Date date = new Date();
//方法二
java.util.Date date = new java.util.Date();
System.out.println(date.getTime());
}
}
💬代码解释:
- 由于
util
和sql
中都存在一个 Date 这样的类,方法一这样的表达形式,就会出现歧义,对 Date 的引用不明确,编译出错。- 可以使用方法二这样的形式,使用完整的类名对其进行实例化。
- 排除这种特殊情况。可以在没有导包的情况下用方法二来导入类也是可行的,缺点在于写法较为麻烦;一般来说在用 import 关键字导入包的情况下,方法一进行实例化会较为普遍。
方法一报错图示:
1.2 再把类丢包里去
想要将类放入包中,首先需要自己先建一个包。
建包创类操作:
一:建包
- 右键 src -> New -> Package
- 输入包名
- 结果图(为了使包更具有层次感,可以通过设置进行操作)
二:创类
- 右键包名(这里选择在 www 这个包下面创建一个类)-> New -> Java Class (如果选择在 jxust 这个包下创建一个类,那么该类将会和 www 这个包同级)
- 输入类名
- 结果图,可以看见这里有两个 TestDemo 类,但是存在于不同的包下面,就不会产生任何的冲突
文件途径:
代码区:
package com.jxust.www;
public class TestDemo {
}
注意:
- 完成上述的操作之后,在文件的最上方会出现一个
package
语句,该条语句指定了该代码在哪个包中,不可以将其删除- 包名通常为
公司的域名的逆置
,差不多就像上述我的举例的那样,但并非硬性规定,也可以选择想起什么名儿就起什么名儿。- 包名要和代码路径相匹配
1.3 包的访问权限控制
在上一章类与对象中,有介绍过类中的 public 和 private 关键字,public 是最为公开的,可以被所有的类所访问,private 是最为私有的,只能被自己的类访问和修改。
当某一个成员没有任何的关键字进行修饰,该成员就受包的访问权限控制
,该成员可以在包内部的其他类使用, 但是不能在包外部的类使用。实际上,这种成员默认被 default(friendly) 所修饰。
📑代码示例:
www 包:
package com.jxust.www;
public class TestDemo {
int a = 18;
}
//定义一个包访问权限的变量a
package com.jxust.www;
public class TestDemo2 {
public static void main(String[] args) {
TestDemo testDemo = new TestDemo();
System.out.println(testDemo.a);
}
}
//执行通过,可以访问的到a
其他包里面:
public class TestDemo {
public static void main(String[] args) {
com.jxust.www.TestDemo testDemo = new com.jxust.www.TestDemo();
System.out.println(testDemo.a);
}
}
//编译错误
1.4 常见的一些系统包
- util 工具包使用的范围很广,非常重要
- lang 包提供了程序设计的基础类,在创造各种基础类型的变量时,都会
自动的导入该包
1.5 静态导入(了解)
可以使用 import static
导入包中的静态的方法和字段
📑代码示例:
求对 a 和 b 变量的平方和进行开平方的结果
import static java.lang.Math.*;
public class TestDemo {
public static void main(String[] args) {
double a = 2,b = 3;
//静态导入的方式
double result = sqrt(pow(a,2) + pow(b,2));
//一般方式
//double result = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));
System.out.println(result);
}
}
💬代码解释:
静态导入的优点就在于可以将代码写起来更加的简单,缺点就在于代码的可读性降低,所以一般来说,静态导入
不太会用到
,了解即可。
二、继承
2.1 初介绍
在正是学习 Java 语言前,就有了解到 Java 语言是面向对象的,而面向对象的基本特征:封装、继承、多态、抽象
在此之前,封装已经有所了解,知道了通过 private 关键字将成员包裹在当前的类中,外界想要对数据进行访问就需要使用已经提供的 get 和 set 方法,从而保证了模块具有较好的独立性,使得程序维护修改较为容易。
现在,我们讲一讲继承这一个基本特征。
日常生活中什么是继承?隔壁小王继承了他的爸爸老王的一大笔财产,这就意味着,原本属于老王的钱小王也可以花了。
面向对象中的继承有着异曲同工之妙,类与类之间会存在着某种关系,被继承的类称为 父类/基类/超类,而继承别的类的类就叫做子类/派生类,类似小王继承了老王的财产一样,子类继承了父类的字段和方法。
此时此刻,你是否…
举个例子:
📑代码示例:
class Animal {
public int age;
public String name;
public void eat() {
System.out.println(this.age +"岁的" + this.name + " 会吃饭");
}
}
class Bird extends Animal{
public void fly() {
System.out.println(this.age +"岁的" + this.name + " 会飞翔");
}
}
class Dog extends Animal{
public String color;
public void bark() {
System.out.println(this.age +"岁的" + this.name + " 会狗叫");
}
}
public class TestDemo {
public static void main(String[] args) {
Dog dog = new Dog();
dog.name = "旺财";
dog.age = 3;
dog.eat();
dog.bark();
}
}
🏸 代码结果:
💬代码解释:
- 创建了三个类,
Animal
类,Bird
类以及Dog
类,这三个类存在着某些关联,鸟是动物,狗也是动物,因此动物所具有的特征(比如有名字,有年龄,会吃饭)这俩都有,如果这些共有的特征在每个类里面都写一遍,就会造成代码冗余。- 此时该代码采取让
Bird
和Dog
分别继承Animal
类,这样这两个类就是所谓子类
,Animal 就是所谓父类
,子类继承了父类的所有公开的字段和方法,达到了代码重用的效果
。
Dog 类的内存分布:
2.2 语法规则
✒️基本语法形式:
class A extends B {
}
注意事项:
- A 代表子类,B 代表父类,关键字
extends
在 Java 中的作用是继承
的意思,使用该关键字指定父类- 在 Java 中不允许多继承的存在,一个子类只能继承
一个
父类- 子类会继承父类所有公开的字段和方法,被 private 关键字修饰的字段和方法,子类是没有办法进行访问的
- 子类可以使用 super 关键字得到父类实例的引用
举例代码改进:
📑代码示例:
class Animal {
public int age;
public String name;
public Animal(int age, String name) {
this.age = age;
this.name = name;
}
public void eat() {
System.out.println(this.age +"岁的" + this.name + " 会吃饭");
}
}
class Bird extends Animal{
public Bird(int age, String name) {
super(age, name);
}
public void fly() {
System.out.println(this.age +"岁的" + this.name + " 会飞翔");
}
}
public class TestDemo {
public static void main(String[] args) {
Bird bird = new Bird(2,"麻雀");
bird.fly();
bird.eat();
}
}
🏸 代码结果:
💬代码解释:
- 当父类创造了带两个参数的构造方法时,
子类
既然已经继承了父类,就需要先帮助父类进行构造
,否则代码就会报错- 子类帮助父类构造方法的快捷步骤:
- 将光标放置在报错之处
- Alt + 回车键
- 选择 Create constructor matching super
- 报错消失,帮助父类构造方法完成
- super() 的作用就是
显示的调用父类的构造方法
- 在代码升级之前并没有报错是因为,编译器默认父类拥有无参的构造方法,默认子类调用父类不带参数的构造方法
2.3 super 关键字
super 关键字表示获取到父类实例的引用
,简而言之,在子类内部调用父类方法或成员。
用法一:
super() 调用父类的构造方法(前面有所介绍)
public Bird(int age, String name) {
super(age, name);
}
注意:一般放在第一行
用法二、三:
super.方法 调用父类的普通方法
super.成员方法 调用父类的普通方法
class Animal {
public int age;
public String name;
public void eat() {
System.out.println(this.age +"岁的" + this.name + " 会吃饭");
}
}
class Bird extends Animal{
public void fly() {
super.eat();
System.out.println(super.age +"岁的" + this.name + " 会飞翔");
}
}
public class TestDemo {
public static void main(String[] args) {
Bird bird = new Bird(2,"麻雀");
bird.fly();
}
}
🏸 代码结果:
💬代码解释:
- 在子类的 fly方法中用关键字 super 调用了父类的 eat 方法,因此 当如我代码这么写的话,只需要在 main 函数中调用了 fly 方法,eat 方法也会被调用
- fly 方法中的 age 是调用父类的 age,name 是继承父类得来的,使用上并没有什么区别,一般当前的类用 this 较为普遍
注意:
super()
和this()
都需要放在第一行,因此两者不能共存
- super 关键字不可以在被
static
修饰的方法中进行使用,因为该关键字依赖当前对象- super 关键字只会指向
最直接
的父类- 当子类和父类拥有同名的字段或方法时,符合
就近原则
使用子类的该字段或方法,若依然想要用父类的该字段或方法,就需要使用到 supersuper
和this
最大的区别
在于,super 表示对当前对象的父类的引用,this 表示对当前对象的引用;另外,查找的范围也有所区别,super 不会查找本类直接调用父类,this 先查找本类,如果本类没有就调用父类
2.4 protected 关键字
如果将某字段用 private 修饰,其子类没有办法访问。用 public 修饰,就没有封装的存在了。
此时,protected
关键字就起到了重要作用,被该关键字修饰的字段和方法可以被其类的子类(同一个包和不同的包都包含在内)和同一个包的其他的类访问到
。
需要注意的是,如果是不同包下面的子类,不可以用对象的引用来访问父类的变量,可以通过 super。如果是同一个包下的话,两种方法都可以。
总结表:
2.5 final 关键字
A类继承了B类,B类继承了C类,C类继承了D类…
像这样层层叠叠更为复杂的继承方式称为多层继承
,即子类还可以进一步的再派生出新的子类,但实际上超过三层的继承关系就需要考虑一下对代码进行重构,否则代码的可读性不高。
想要在语法上限制类被继承
,final 关键字起到了重要作用。
之前有了解到,被 final 关键字修饰的变量或者字段,表示常量,是没有办法被修改的。
该关键字也可以修饰类,表示被修饰的类是不能被继承
的。如果继承了,就会编译错误。
完!