一、工具类&制作帮助文档
1.1 工具类
前面一天,我们学习static关键字,我们知道如果一个方法被static修饰,那么这个方法就可以用类名调用。接下来,我们利用static的这个特性来学习工具类。
首先我们认识一下什么是工具类:如果一个类中的方法全都是static修饰的方法,那么这个类就称为工具类
之所以称之为工具类,是因为类中的方法都是静态方法,调用起来特有方法,就像一个工具一样,拿起来就能用。如下图所示:
1.2 打jar包
同学们,刚才我们已经写好了一个工具类,而且类中的方法都是一些比较通用的方法,所谓通用方法意思就是在任何一个项目中可以用到的方法。为了把工具类编译好的字节码分享给别人使用,或者以后在其他项目中使用到,我们可以把写好的类打成一个jar包。
- jar包:也就是后缀名为.jar的文件,也叫jar文件
- jar(英文:JavaARchive,Java归档的意思),一般情况下一个jar包中会打包多个class文件。
- 简单理解:jar包就是封装有class文件的压缩包
Idea提供了制作Jar包的功能,按照下图的步骤一步一步点击就行
jar包的输出目标默认在,工程目录的out\artifacts
目录。比如我的工程目录是C:\IdeaProjects\javase-advanced\
在工程目录下有out\artifacts\day02_jar_abstract_interface_polymorphic_jar
,jar包就在这里
打好jar包之后怎么用呢
如果其他的模块中想要使用别人jar包中的类和方法,则需要引入jar包,引入jar包的步骤如下图所示
第一步:先在模块的目录下新建一个lib文件夹
第二步:把jar文件复制到lib文件夹下
第三步:选择lib文件夹下的jar文件,右键点击Add As Library
做完前面三步就引入成功了,就可以使用jar包中的代码了
引入成功之后,就可以使用jar包中的类中的方法了
1.3 制作帮助文档
同学们我们现在知道如何制作jar包,也知道如何引入jar包了,但是如果jar包中提供的了很多个类,一个类中又有很多个方法,作为使用者我怎么知道哪个类是干什么用的?哪个方法是什么意思呢?
其实我们制作jar包后,还应该制作一个帮助文档,一起给别人,别人才能根据帮助文档来学习类和方法该怎么用。
需要特别注意:帮助文档中类、方法、参数、返回值的解释,必须通过文档注释进行说明
Idea提供了制作帮助文档的功能,按照步骤点击
此时指定的帮助文档的生成目录下,会出现很多html文件,我们找到index.html这就是帮助文档的主页
点击index.html看一下,效果如下图所示
1.4 Math工具类
刚才我们是自己制作的帮助文档,其实Java的JDK中本身就内置了很多写好的类,并且给我提供了帮助文档,我们听过学习帮助文档就可以学习JDK提供的类该怎么使用。
其中就有一个类叫Math类,我们去帮助文档中查一下。查看API文档我们会发现Math类中的方法都是static修饰的方法,所以Math类就是一个工具类。
public class Demo{
public static void main(String[] args) {
//1.求-10的绝对值
System.out.println(Math.abs(-10)); //10
//2.对7.8向上取整
System.out.println(Math.ceil(7.8)); //8.0
//3.对7.8向下取整
System.out.println(Math.floor(7.8)); //7.0
//4.对3.5、3.1四舍五入
System.out.println(Math.round(3.5)); //4
//5.获取7,,9两个数的最大值
System.out.println(Math.max(7,9)); //9
//6.求2的3次幂
System.out.println(Math.pow(2,3)); //8
//7.生产一个随机数 范围 [0.0, 1.0)
System.out.println(Math.random()); //0.87
}
}
二、包和导包&权限修饰符
2.1 包和导包
- 包的作用:包是用来描述一个类在哪个文件夹下,用来对类文件进行分类管理的。
- 包的定义格式:
package 包名;
多级包需要用.
隔开,比如:package com.itheima.demo1;
//定义包:表示Student类在com.itheima.demo1包下
package com.itheima.demo1;
public class Student{
}
- 访问不同包下的类需要导包,格式如下
package com.itheima.demo2;
//导入demo1包下的Student类
import com.itheima.demo1.Student;
public class Demo{
public static void main(String[] args){
//直接通过包名访问
com.itheima.demo1.Student s1 = new com.itheima.demo1.Student();
//导包后,就不需要用包名访问了
Student s2 = new Student();
}
}
2.2 权限修饰符
权限修饰符一共有四种,用来限制类的成员能够被访问的范围;他们的作用范围如下图所示
三、抽象类
3.1 抽象类和抽象方法
如果一个类被abstarct修饰这个类就是抽象类;如果一个方法被abstract修饰,并且没有方法体,这个方法就是抽象方法。
注意:抽象类都是作为父类使用的,子类继承抽象类必须重写所有的抽象方法。
3.2 抽象的应用(模板方法模式)
利用抽象类的特点,可以用抽象类和抽象方法实现模板设计模式;意思就是将能确定的功能写成实例方法,将不能确定的功能写成抽象方法,这个类就是一个模板类。子类继承抽象类只需要复写抽象方法就可以了,大大提高了代码的复用性。
如下图所示,把写作为功能写成一个模板类,能确定是作文的开头和结尾,正文不确定。
在测试类中创建Tom对象,调用写作文的方法
public class Demo3{
public static void main(String[] args){
Tom tom = new Tom();
//Tom要写作文,直接调用wirte方法就可以了
tom.write();
Anna anna = new Anna();
//anna要写作文,直接调用wirte方法就可以了
anna.write();
}
}
四、接口
4.1 接口的定义
Java中的接口也是一种标准,接口中的方法全都是抽象方法
接口使用interface
来定义,格式如下
4.2 接口的实现
接口定义好了之后,需要有类去实现接口,实现接口的关键字实
implements
。一个类可以实现多个接口
4.3 抽象类与接口的区别
我们目前学习了类可以继承父类,类也可以实现接口,那么接口与接口是什么关系呢?
类能不能在继承父类的同时实现多个接口呢?接下来我们把这些关系捋一捋。
- 继承父类、实现接口是不冲突的,一个类可以在继承父类的同时,实现多个接口。
通过下面代码演示一下,大家只需要知道语法规则就行。先不要管有什么用,现在学习的仅仅只是语法规则。
定义两个接口
public interface Inter1{
public void show1();
}
public interface Inter2{
public void show2();
}
一个接口继承多个接口,相当于把多个接口中的方法集于一身。
public interface Inter3 extends Inter1,Inter2{
public void show3();
}
定义一个父类
public abstract class Fu{
public abstract void show4();
}
写一个子类,继承Fu类,同时实现Inter1和Inter2两个接口。
public class Zi extends Fu implements Inter3{
//既要复写父类的抽象方法,也需要复写所有接口中的抽象方法
public void show1(){
System.out.println("我是复写Inter1中的show1方法");
}
public void show2(){
System.out.println("我是复写Inter2中的show2方法");
}
public void show3(){
System.out.println("我是复写Inter3类中的show3方法");
}
public void show4(){
System.out.println("我是复写Fu类中的show4方法");
}
}
4.4 JDK8对接口的更新
从JDK8开始,接口中新增了一些可以带方法体的方法。
public interface Inter{
//默认方法,类似于类中的普通方法
public default void test1(){
}
//静态方法,和类中的静态方法一样,特点也一样
public static void test2(){
}
//私有方法,和类中的私有方法,特点也一样
private void test3(){
}
}
五、多态
5.1 多态概述
像这种用父类变量接收子类对象的写法,就是一种多态的写法。代码如下
写一个Animal父类
public abstract class Animal{
public void eat();
}
再写一个Animal的子类,Dog类
public class Dog extends Animal{
@Override
public void eat(){
System.out.println("狗吃骨头");
}
}
再写一个Animal的子类,Cat类
public class Cat extends Animal{
@Override
public void eat(){
System.out.println("猫在吃小鱼干");
}
}
再写一个测试类,在测试类中创建Dog的对象,创建Cat类的对象,用多态的形式创建。
public class Demo{
public static void main(String[] args){
Animal dog = new Dog();
dog.eat(); //这里执行的是Dog类的eat()方法
Animal cat = new Cat();
cat.eat(); //这里执行的是Cat类的eat()方法
}
}
5.2 多态的好处和弊端
多态的好处:
当把方法的形参写成父类类型或者接口类型时,调用方法时可以传递父类的子类对象,或者接口的实现类对象。
public class Demo{
public static void main(String[] args){
Dog dog = new Dog();
feed(dog);
Animal cat = new Cat();
feed(cat);
}
//这里的Animal a既能接收Dog对象,也能接收Cat对象
public static void feed(Animal a){
a.eat();
}
}
多态的弊端:
在多态的形式下,不能调用子类或者实现类的特有方法。
假设在Dog类中有一个swimming()方法
public class Dog extends Animal{
@Override
public void eat(){
System.out.println("狗吃骨头");
}
public void swimming(){
System.out.println("狗刨得贼快~~~");
}
}
在测试类的feed方法中,尝试调用Dog类的特有方法
public class Demo{
//这里的形参Animal a在方法中,并不能确定是Dog对象还是Cat对象
//所以不能调用Dog或者Cat类的特有方法
public static void feed(Animal a){
a.eat();
//swimming()是Dog类的特有方法,试试这里会报错。
a.swimmming();
}
}
5.3 多态的转型
如果知道多态的形式接收的是哪一个子类对象,或者哪一个实现类的对象,则可以进行向下转型。
如果类型转换错了,或出现ClassCastException,如下图所示
为了防止类型转换出现问题,可以在转换之前进行判断。这里需要用到一个关键字叫instanceof,作用是判断一个对象是否是指定类的实例,满足条件再转换,转换之后就可以调用子类特有方法了