本篇文章是根据视频学的,来源如下所示:
教程来源: | java基础到高级_零基础自学Java–尚硅谷–宋红康 |
教程视频地址: | java基础到高级_零基础自学Java--尚硅谷--宋红康_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV1ny4y1Y7CW |
目录
1.static关键字的引入
-
当我们编写一个类时,其实就是在描述其对象的属性和行为,而并没有产生实质上的对象,只有通过 new 关键字才会产生出对象,这时系统才会分配内存空间给对象,其方法才可以供外部调用。我们有时候希望无论是否产生了对象或无论产生了多少对象的情况下, 某些特定的数据在内存空间里只有一份 ,例如所有的中国人都有个国家名称,每一个中国人都共享这个国家名称,不必在每一个中国人的实例对象中都单独分配一个用于代表国家名称的变量。(PPT原始内容)
2.静态变量与实例变量的对比(代码见下面)
3.static修饰属性的其他说明(代码见下面)
4.类变量和实例变量的内存解析(代码见下面)
5.static修饰方法(代码见下面)
6.属性或者方法是否应该static的经验之谈
package com.atshangguigu.java;
/*
* static关键字的使用
* 1.static:静态的
* 2.static可以用来修饰:属性 方法 代码块 内部类
* 3.使用static修饰属性:静态变量(或者说是类变量)
* 3.1属性:按是否使用static修饰,分为静态属性 vs 非静态属性(实例变量)
* 实例变量:我们创建了类的多个对象,每个对象都有独立的一套类中的实例变量,非静态属性.
* 当修改其中的一个对象的非静态属性时,不会导致其他对象之中的同样的属性值的改变.
* 静态变量:我们创建了类的多个对象,多个对象共享同一个静态变量.当通过某一个对象修改静态
* 变量的时候,会导致其他对象调用的时候是修改过的(可以将厨房与厕所理解成这个)
* 3.2 static修饰属性的其他说明:
* 1.静态变量随着类的加载而加载,可以通过"类.静态变量"的方式调用.
* 2.静态变量的加载要早于对象的创建,而实例对象是在有了对象以后才会出现的.
* 3.由于类只加载一次,则静态变量在内存之中 也会只存在一份---已经缓存了起来:存在方法区的静态域之中
* 4. 类变量 实例变量
* 类 ok
* 对象 ok ok
* 3.3 静态属性的举例:system.out;Math.PI;
*
*
* 4.使用static修饰方法:静态方法
* 1.静态方法随着类的加载而加载,可以通过"类.静态方法"的方式进行调用
2. 静态方法 非静态方法
* 类 ok
* 对象 ok ok
* 3.静态的方法之中只能都调用静态的的方法或者属性
* 非静态方法之中,既可以调用非静态的方法或者属性,也可以调用静态的方法或者属性
* 5.static注意点:
* 1.在静态的方法以内,不能使用this关键字 super关键字
* 2.关于静态属性欲静态方法的使用都是从生命周期的角度进行理解.
* 6. 在开发之中如何确定一个属性要不要声明为一个static?
* 答:(五号钱同学请回答[眼镜咋摘了],不会回答:暂时没有)
* 属性是可以被多个对象所共享的,不会随着对象的不同而不同
* 在开发的过程之中如何确定一个方法要不要声明一个static?
* 答:操作静态属性的方法,通常设置成为static
* 工具类的方法一般我们是声明为static,比如:Math Arrays Collections
*/
public class Static
{
public static void main(String[] args) {
Chinese.nation = "中国";//这里的含义是随着类的加载而加载,
//Chinese.name = "海绵宝宝"; //使用这个类去调用这个属性,是调用不了的,编译是不通过的
Chinese.show();
Chinese c1 = new Chinese();
c1.name = "康师傅";
c1.age = 41;
Chinese c2 = new Chinese();
c2.name = "宝强";
c2.age = 38;
c1.nation = "CHN";//Static的修饰---北上广深,现在杭州崛起了
System.out.println(c2.nation);//(老师说天津也不错哦!---天飘的迷茫)
}
}
//中国人
class Chinese
{
String name;
int age;
static String nation;
public void eat()
{
System.out.println("陕西的羊肉泡馍比较好吃");
//调用非静态的结构
this.info();
//调用静态结构
fly();
System.out.println("nation:" + nation);//这里的nation是相当于Chinese.nation
}
public static void show()//随着类的加载而加载---通过类进行调用
{
System.out.println("我是一名堂堂正正的中国人");
//可以调用静态的结构,不可以调用非静态的结构
System.out.println(nation);//这里省略的不是this.而是Chinese.
fly();
}
public void info()
{
System.out.println("name:" + name + ",age:" + age);
}
public static void fly()
{
System.out.println("我会飞");
}
}
7.自定义ArrayUtil工具类的优化
- 做一个小的练习(在之前的基础上面进行改进)
- ArrayUtil.java
package com.atshangguigu.java;
/*
* 自定义数组的工具类
*/
public class ArrayUtil {
//求最大值
public static int getMax(int[] arr)
{
int max = arr[0];//最大值
for(int i = 0;i < arr.length;i++)
{
if(max < arr[i])
{
max = arr[i];
}
}
return max;
}
//求最小值
public static int getMin(int[] arr)
{
int min = arr[0];//最小值
for(int i = 0;i < arr.length;i++)
{
if(min > arr[i])
{
min = arr[i];
}
}
return min;
}
//求总和
public static int getSum(int[] arr)
{
int add = 0;
for(int i = 0;i < arr.length;i++)
{
add += arr[i];
}
return add;
}
//求平均值
public static double getAvg(int[] arr)
{
int add = 0;
double ava;
for(int i = 0;i < arr.length;i++)
{
add += arr[i];
}
ava = add/(arr.length);
return ava;
}
//反转
public static void reverse(int[] arr)
{
for(int i = 0,j = arr.length-1;i < j;i++,j--)
{
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
//复制
public static int[] copy(int[] arr)
{
int[] arr1 = new int[arr.length];
for(int i = 0;i < arr.length;i++)
{
arr1[i] = arr[i];
}
return arr1;
}
//排序
public static void sort(int[] arr)
{
for(int i = 0;i < arr.length-1;i++)
{
for(int j = 0;j <arr.length-1-i;j++)
{
if(arr[j]<arr[j+1])
{
/*int temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
*/
swap(arr,j,j+1);
}
}
}
}
public static void swap(int[] arr,int i,int j)
{
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
//遍历
public static void print(int[] arr)
{
for(int i = 0;i < arr.length;i++)
{
System.out.print(arr[i] + "\t");
}
}
//查找
public static int getIndex(int[] arr,int dest)
{
for(int i = 0;i < arr.length;i++ )
{
if(dest == arr[i])//这里需要注意equals()的使用
{
System.out.println("恭喜你,找到啦!");
return i;//替代break
}
}
return -1;//返回一个负数表示没有找到
}
}
-
ArrayUtilTest.java
package com.atshangguigu.java;
public class ArrayUtilTest {
public static void main(String[] args) {
//ArrayUtil util = new ArrayUtil();
int[] arr = new int[]{32,3,1,64,56,5,6,99,56,102,95,88,213,1,23,465,114,954};
int max = ArrayUtil.getMax(arr);
System.out.println("最大值为" + max);
System.out.print("排序前:");
ArrayUtil.print(arr);
System.out.println();
System.out.print("排序后:");
ArrayUtil.sort(arr);
ArrayUtil.print(arr);
System.out.println("查找");
int index = ArrayUtil.getIndex(arr, 5);
if(index != 0)
{System.out.println("找到了,索引地址为:" + index);
}
else
{System.out.println("没有找到");
}
}
}
8.static的应用举例
package com.atshangguigu.java;
/*
* static 关键字的使用
*/
public class CircleTest {
public static void main(String[] args) {
Circle c1 = new Circle();
Circle c2 = new Circle();
Circle c3 = new Circle(3.4);
System.out.println("c1的id是:" + c1.getId());
System.out.println("c2的id是:" + c2.getId());
System.out.println("c3的id是:" + c3.getId());
System.out.println("创建的圆形的个数:" + Circle.getTotal());
//final是一个常量的标志:后面会去提及:类中的常量一般是声明为static类型的
}
}
class Circle
{ //属性
private double radius;
private int id;
//调用了一个添加的方法
public Circle()
{
id = into++;//这里提现的是进行static状态下的增加
total ++;
}
public Circle(double radius)
{
this();//相当于下面写的代码
/*id = into++;//这里提现的是进行static状态下的增加
total ++;//(这里需要注意的)
*/
this.radius = radius;
}
//私有的属性
private static int total;//记录圆的个数
private static int into = 1000;//static声明的属性被所有对象做共享
//方法
public double findArea()
{
return Math.PI * radius * radius;
}
//get与set的一个方法
public double getRadius() {
return radius;
}
public void setRadius(double radius) {
this.radius = radius;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public static int getTotal() {//那么如果一个属性是static,那么它的方法也是默认为static类型的
return total;
}
}
9.static课后练习:账户信息
- Account.java
package com.atshangguiguexer;
/*
编写一个类实现银行账户的概念,包含的属性有“帐号”、“密码”、“存款余额”、“利率”、“最小余额”,定义封装这些
属性的方法。账号要自动生成。
编写主类,使用银行账户类,输入、输出3个储户的上述信息。
考虑:哪些属性可以设计成static属性。
*/
public class Account {
//1.属性
private int id;
private String pwd = "19991123";//密码
private double banlance;
private static double interestRate;//利率
private static double minMoney = 1.0;
private static int init = 1001;//自动生成id
//2.进行方法的声明
//原来的属性是静态的 那么它的方法现在还是静态的
public String getPwd() {
return pwd;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
public static double getInterestRate() {
return interestRate;
}
public static void setInterestRate(double interestRate) {
Account.interestRate = interestRate;
}
public static double getMinMoney() {
return minMoney;
}
public static void setMinMoney(double minMoney) {
Account.minMoney = minMoney;
}
public int getId() {
return id;
}
public double getBanlance() {
return banlance;
}
//3.构造器
public Account()
{
id = init++;
}
public Account(String pwd,double banlance)
{
this();
this.pwd = pwd;
this.banlance = banlance;
}
@Override
public String toString() {
return "Account [id=" + id + ", pwd=" + pwd + ", banlance=" + banlance + "]";
}
}
- AccountTest.java
package com.atshangguiguexer;
public class AccountTest {
public static void main(String[] args) {
Account acct1 = new Account();
Account acct2 = new Account("350340",500000.0);
Account.setInterestRate(0.012);
Account.setMinMoney(10);
System.out.println(acct1);
System.out.println(acct2);
}
}
10.设计模式与单例设计模式
-
设计模式 是在大量的实践中总结和理论化之后优选的代码结构、编程风格、以及解决问题的思考方式 。设计模免去我们自己再思考和摸索。就像是经典的棋谱,不同的棋局,我们用不同的棋谱。 ” 套路 ”----一共23种模式
-
不同的语言有不同的设计模式---java使用设计模式是比较多的(初级阶段暂时不考虑)
-
后面可以买一本数去看一看---大话设计模式 23种设计模式 深入浅出设计模式
-
所谓类的单例设计模式,就是采取一定的方法保证在整个的软件系统中,对某个类 只能存在一个对象实例 ,并且该类只提供一个取得其对象实例的方法。如果我们要让类在一个虚拟机中只能产生一个对象,我们首先必须将类的 构造器的访问权限设置为 private ,这样,就不能用 new 操作符在类的外部产生类的对象了,但在类内部仍可以产生该类的对象。因为在类的外部开始还无法得到类的对象,只能 调用该类的某个静态方法 以返回类内部创建的对象,静态方法只能访问类中的静态成员变量,所以,指向类内部产生的 该类对象的变量也必须定义成静态的 。(PPT的内容)
11.单例的饿汉式的实现
package com.atshangguiguexer;
/*
* 单例设计模式:
* 1.所谓类的单例设计模式,就是采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例.
* 2.如何实现?
*/
public class SingletonTest1 {
public static void main(String[] args) {
Bank bank1 = Bank.getInstance();
Bank bank2 = Bank.getInstance();
//这里去判断是否是一个,饿汉式
System.out.println(bank1 == bank2);
}
}
//饿汉式
class Bank
{
//步骤1.私有化类的构造器:避免在外面构造多个对象
private Bank()
{
}
//步骤2.内部创建类的对象
//步骤4.要求这个对象也必须是静态的
private static Bank instance = new Bank();
//步骤3.提供公共的方法,返回类的对象
public static Bank getInstance()
{
return instance;//静态的方法只能调用静态的对象
}
}
12.单例的懒汉式的实现
package com.atshangguiguexer;
/*
* 单例模式的懒汉式的实现
*/
public class SingleTest2 {
public static void main(String[] args) {
Order order1 = Order.getInstance();
Order order2 = Order.getInstance();
System.out.println(order1 == order2);
}
}
class Order
{
//1.私有化类的构造器
private Order()
{
}
//2.声明当前类的对象,没有初始化
//4.此对象也必须声明为static类型
private static Order instance = null;
//3.声明public static的返回类对象的一个方法
public static Order getInstance()
{
if(instance == null)
{
instance = new Order();//创建多个当前的对象,不是之前的唯一一个,因此需要进行一个判断
}
return instance;
}
}
- 懒汉式是什么时候用的时候什么时候进行造一个对象,然而饿汉式是先要造出来一个对象,然后再使用,这就是饿汉式和懒汉式的不同---------这是自己的理解.
- 注意:面试的时候应当注意不要把这两个弄反了
13.饿汉式和懒汉式的对比
* 3.区分饿汉式与懒汉式的不同.
* (1)饿汉式:(提前创建出来)
* 坏处:对象的加载时间过长.
* 好处:线程是安全的---线程需要注意后面要学的[银行的取钱问题 抢票的问题]
* (2)懒汉式:(非必须是不会创造相应的对象)
* 好处:延迟对象的一个创建.--
* 坏处:线程是不安全的---就是在null阻塞的时候,可能会导致出现两个
14.单例模式的使用场景
-
单例模式的优点:由于单例模式只生成一个实例, 减少了系统性能开销 ,当一个对象的产生需要比较多的资源时,如读取配置、产生其他依赖对象时,则可以通过在应用启动时直接产生一个单例对象,然后永久驻留内存的方式来解决。举例:java.lang.Runtime
- 单例模式的应用场景
15.理解main()方法的语法
- MainDemo.java
package com.atshangguiguexer;
public class MainDemo {
public static void main(String[] args) {
for(int i = 0;i < args.length;i++)
{
System.out.println("输出的是" + args[i]);
}
}
}
- MainTest.java
package com.atshangguiguexer;
/*
* main()的使用说明:
* 1.main()方法作为程序的入口出现
* 2.main()方法也是一个静态的方法,普通的静态方法
* 3.main()的形参出现,可以作为与控制台交互的一种方式(之前是使用Scanner)
*/
public class MainTest {
//因为main()是静态的,因此为什么我们一开始直接进行调用相应的属性掉用不了,然后必须通过对象进行访问.
public static void main(String[] args) {//体现它是一个入口
Main.main(new String[100]);
}
}
class Main
{
public static void main(String[] args) {
for(int i = 0; i < 120; i++)
{
System.out.println(i);
}
}}
-
这里应当注意的是与系统的交互:交互的过程与第一节课讲到的内容有关--首先打卡编译器--复制源码--删掉源码之中的开头的部分--进行javac xxx.java--进行java xxx "X" "X" "X"即可.
16.类中代码块结构的使用
package com.atshangguigu.java3;
/*
* 类的成员之四:代码块(或者初始化块)
* 1.代码块的作用:用来初始化类 对象
* 2.代码块如果有修饰的话,只能用static
* 3.分类:静态代码块 pk 非静态代码块
* 4.静态代码块
* 内部可以有输出语句
* 随着类的加载而执行---这里比较过分的(自动执行的),只执行一次
* 如果一个类之中定义了多个代码块,则按照声明的先后顺序进行执行
* 静态代码块的执行先与非静态代码块(只和对象有关系)
* 静态代码块内只能调用静态的属性与方法,不能够调用非静态的属性以及方法
* 5.非静态代码块
* 内部可以有输出语句
* 随着对象的创建而执行
* 每创建一次对象,就执行一次非静态代码块
* 作用:可以在创建对象的时候,对对象的属性等进行初始化(每造一次对象进行一次)
* 如果一个类之中定义了多个非静态代码块,按照先后顺序进行执行
* 非静态代码块可以调用静态的属性 静态的方法,或者非静态的属性与方法
* 对属性可以赋值的位置:
* a.默认初始化
* b.显式初始化
* c.构造器之中进行初始化
* d.有了对象以后,可以通过对象.属性或者对象.方法的方式,进行赋值
* e.在代码块之中进行赋值
*/
public class BlockTest {
public static void main(String[] args) {
String desc = Person.desc;
System.out.println(desc);
Person p1 = new Person();
Person p2 = new Person();
System.out.println(p1.age);
Person.info();
}
}
class Person
{ //属性
String name;
int age = 23;
static String desc = "我是一个菜鸟,不会吃虫子的菜鸟";
//构造器
public Person()
{}
public Person(String name,int age)
{
this.name = name;
this.age = age;
}
//static代码块:就是一对大括号
static{
System.out.println("我是一只猪");
desc = "我需要赚钱";//对于类之中的静态的属性进行了赋值
}
static{
System.out.println("我是一只猪猪侠");
desc = "我需要赚很多的钱";//对于类之中的静态的属性进行了赋值
info();//只能调用静态的结构
}
//非static代码块
{
System.out.println("我是一只猫");
}
{
System.out.println("我是快乐的星猫");
info();//调用静态结构
eat();//调用非静态结构
}
//方法
public void eat()
{
System.out.println("吃饭");
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
public static void info()
{
System.out.println("这两天没有什么任务");
}
}
17.开发中代码块的使用举例
- 属性里面不可以进行方法的调用.
- 这节课没听懂
18.代码块的课后练习
19.属性赋值的先后顺序
package com.atshangguigu.java3;
/*
* 对属性可以赋值的位置:
* a.默认初始化
* b.显式初始化
* c.构造器之中进行初始化
* d.有了对象以后,可以通过对象.属性或者对象.方法的方式,进行赋值
* e.在代码块之中进行赋值
*
* 执行的先后顺序a b/e(看b和e谁是后写的) c d
*/
public class OrderTest {
public static void main(String[] args) {
Order order = new Order();
System.out.println(order.orderId);//结果是4
}
}
class Order
{
{
orderId = 4;
}
int orderId = 3;
}
20.final修饰类的方法
21.final修饰属性
22.final修饰局部变量
package com.atshangguigu.java3;
/*
* final:最终的
* 1.final可以修饰的结构:类 方法 变量
*
* 2.final用来修饰一个类:此类不能被其他的类继承
* 比如:String类 System类 StringBuffer类
*
* 3.final 用来修饰一个方法:表明这个方法不能够被重写了---然后呢?就没有然后了,就辞职了
* 比如:Object类之中的getClass();
* 4.final 用来修饰变量:此时的变量就称为是一个常量.
* 4.1 final修饰属性:可以考虑赋值的位置有:(1)显式初始化 (2)代码块中进行赋值,外部初始化
* (3)构造器之中进行初始化
* 方法之中不可以调用final,对象调用方法一般是对相应的值的修改
* 4.2 final修饰局部变量:
* 当final修饰形参时候,表明这个形参是个常量.当我们调用这个方法的时候,给常量形参赋一个实参,一旦赋值以后
* 就只能在这个方法体内部使用这个形参,但是不能够进行重新赋值的
* static final :用来修饰属性:全局常量
*/
public class FinalTest {
final int width = 10;
final int WIDTH = 0;
final int LEFT;
final int ZUIYOU;
{
LEFT = 1;
}
public FinalTest()
{
ZUIYOU = 20;
}
public FinalTest(int n)
{
//this();
ZUIYOU = n;
}
public void doWidth()
{
//width = 20;
}
public void show()
{
final int NUM = 0;//常量
}
public void show (final int num)
{
//num = 20;编译是不通过的
System.out.println(num);
}
public static void main(String[] args) {
int num = 10;
num += 5;
FinalTest test = new FinalTest();
test.show(12);
}
}
final class FinalA//这里的含义是不能有子类了(就是独苗了,绝了)
{
}
/*class B extends FinalA//这里的含义是不能够继承上面的类
{
}*/
class aa
{
final public void show()
{}
}
class BB extends aa
{/*
public void show()
{}
*/
}
23.final课后练习
-
题目一:注释里面是对的,return ++x;是错误的;
-
题目二:o.i++就可以想想成你的对象,final,它的年龄是变化的.
24.每日一考
- 1. static 修饰的属性,相较于实例变量,有哪些特别之处(>=3点)
随着类的加载而加载;
早于对象的创建;
只要权限允许,可以通过”对象.static属性”的方式进行调用;存在于方法区的静态域
- 2. final 可以用来修饰哪些结构,分别表示什么意思
(陈周:没在)(张一宁)见前面的代码,更加清晰
- 3. 代码实现单例模式的饿汉式(线程更加安全)
- 4. 代码实现单例模式的懒汉式
- 5. 类的属性赋值的位置有哪些?先后顺序为何?
默认初始化
显式初始化 、代码块中初始化
构造器中初始化
通过”对象.属性” 或”对象.方法”的方式赋值
25.抽象类和抽象方法的使用
package day15;
/*
* abstract关键字的使用
* 1.abstract:抽象的
* 2.abstract可以用来修饰的结构:类 方法
* 3.abstract修饰类:抽象类
* 此类是不可以实例化
* 抽象类之中有构造器,便于子类对象实例化的时候进行调用(子类对象实例化的全过程)
* 开发之中,会提供抽象类的子类,让子类进行实例化,完成相应的操作(弹幕:一切为了儿子)
* 4.abstract修饰方法:抽象方法
* 抽象方法只有方法名字,没有方法体.
* 包含抽象方法的类一定是一个抽象的类.反之,类是一个抽象类,不一定有一个抽象方法.
* 若子类重写了父类之中的所有抽象类,则子类是可以实例化的.若子类没有重写,那么子类就需要声明为是abstract类型的
*
*/
public class AbstractTest {
public static void main(String[] args) {
//Person p1 = new Person(); //不能够造对象了
}
}
abstract class Creature
{
public abstract void breath();
}
abstract class Person extends Creature
{
//属性
String name;
int age;
//构造器
public Person()
{}
public Person(String name,int age)
{
this.name = name;
this.age = age;
}
//方法
public void eat()
{
System.out.println("早上刚刚从学五食堂吃了三个炸饺,但是没吃饱");
}
public void walk()
{
System.out.println("最近没有跑步");
}
//抽象方法是(报错:解决方法如下面)
public abstract void abs();
}
class Student extends Person//解决方法2:进行继承,并且将其声明为abstract
{
public Student(String name,int age)
{
super();
}
public void abs()
{
System.out.println("解决方法1:重写");
}
public void breath()
{
System.out.println("感冒了,呼吸不畅");
}
}
26.抽象的应用场景使用
- 本节是对前面的一个求面积的题进行说明,就是在求面积的地方加上了abstract,也就是它的子类都是需要进行重写的.
27.abstract使用中的注意点
- * abstract使用上的注意点:
* 1.abstract不能够用来修饰:属性 构造器等结构
* 2.abstract不能用来修饰私有方法(因为private的方法是不可以进行重写的) 静态方法(静态方法也是不可以被重写) final的方法
28.抽象性的基本练习:基本操作
- 上面的思考题在上面的三节课都提到了
- Employee.java
package day15;
/*
* 编写一个Employee类,声明为抽象类,
包含如下三个属性:name,id,salary。
提供必要的构造器和抽象方法:work()。
*/
public abstract class Employee {
private String name;
private int id;
private double salary;
public Employee()
{
super();
}
public Employee(String name,int id,double salary)
{
this.name = name;
this.id = id;
this.salary = salary;
}
public abstract void work();
}
- Manager.java
package day15;
/*
* 对于Manager类来说,他既是员工,还具有奖金(bonus)的属性。
*/
public class Manager extends Employee{
private double bonus;//奖金
public Manager(double bonus) {
super();
this.bonus = bonus;
}
public Manager(String name, int id, double salary, double bonus) {
super(name, id, salary);
this.bonus = bonus;
}
@Override
public void work() {
System.out.println("给员工发钱钱");
}
}
- Commenemployee.java
package day15;
public class CommonEmployee extends Employee{
@Override
public void work() {
System.out.println("努力干活,工作");
}
}
- EmployeeTest.java
package day15;
/*
*
*/
public class EmployeeTest {
public static void main(String[] args) {
Employee manager = new Manager("Yang",0102, 12345, 153);//多态的使用
manager.work();
CommonEmployee commonEmployee = new CommonEmployee();
commonEmployee.work();
}
}
29.创建抽象类的匿名子类操作
- 12
- 12
- 12
30.模板方法的设计模式及应用场景
package day15;
/*
* 抽象类的应用:模板方法的设计模式
*/
public class Template {
public static void main(String[] args) {
TemplateTest t = new SubTemplate();
t.spendTime();
}
}
abstract class TemplateTest
{ //用来计算某个代码执行所花费的时间
public void spendTime()
{
long start = System.currentTimeMillis();
code();
long end = System.currentTimeMillis();
System.out.println("花费的时间是" + (end-start));
}
public abstract void code();
}
class SubTemplate extends TemplateTest
{
@Override
public void code() {
for(int i = 2;i <= 1000;i++)
{
boolean isFlag = true;
for(int j = 2;j <= Math.sqrt(i);j++)
{
if(i%j == 0)
{
isFlag = false;
break;
}
}
if(isFlag)
{
System.out.println(i);
}
}
}
}
- 下面的代码是直接复制老师的进行操作的
package day15;
//抽象类的应用:模板方法的设计模式
public class TemplateMethodTest {
public static void main(String[] args) {
BankTemplateMethod btm = new DrawMoney();
btm.process();
BankTemplateMethod btm2 = new ManageMoney();
btm2.process();
}
}
abstract class BankTemplateMethod {
// 具体方法
public void takeNumber() {
System.out.println("取号排队");
}
public abstract void transact(); // 办理具体的业务 //钩子方法
public void evaluate() {
System.out.println("反馈评分");
}
// 模板方法,把基本操作组合到一起,子类一般不能重写
public final void process() {
this.takeNumber();
this.transact();// 像个钩子,具体执行时,挂哪个子类,就执行哪个子类的实现代码
this.evaluate();
}
}
class DrawMoney extends BankTemplateMethod {
public void transact() {
System.out.println("我要取款!!!");
}
}
class ManageMoney extends BankTemplateMethod {
public void transact() {
System.out.println("我要理财!我这里有2000万美元!!");
}
}
31.抽象类的课后练习
32.接口的理解
- 下面的这个图片很好的说明了接口与继承之间的区别
33.接口的定义
package com.atshangguigu.java;
/*
* 接口的使用
* 1.接口使用interface来进行定义
* 2.Java中,接口和并列是两个结构
* 3.如何定义接口:定义接口之中的成员
* 3.1 JDK7以前:只能定义全局常量和抽象的方法
* 全局常量:public static final,但是书写的时候可以省略
* 抽象方法:public abstract
* 3.2 JDK8以后:除了定义全局常量和抽象的方法,还可以定义静态方法 默认方法
* 4.接口之中是不能定义构造器的!意味着接口是不可以进行实例化的.---跟类去发生关系
* 5.Java开发的过程之中,接口都是通过类去实现(implements),而不是继承.
* 如果实现类覆盖(重写)了接口之中的所有抽象的方法,则此实现类就可以进行实例化
* 如果实现类没有覆盖接口之中所有的抽象方法,则此实现类仍然为一个抽象类
*
*
*
*/
public class InterfaceTest {
public static void main(String[] args) {
System.out.println(Flyable.MAX_SPEED);
System.out.println(Flyable.MIN_SPEED);
//Flyable.MIN_APEED = 2.0;
Plane plane = new Plane();
plane.fly();
}
}
interface Flyable
{
//全局常量
public static final int MAX_SPEED = 7000;//第一宇宙速度
int MIN_SPEED = 1;//这里只是对public static final进行省略
//抽象方法
public abstract void fly();
void stop();//省略了public abstract
//构造器
/*public Flyable()
{}*/
}
class Plane implements Flyable
{
@Override
public void fly() {
System.out.println("通过机翼飞");
}
@Override
public void stop() {
System.out.println("通过降落在地面上,制动停止");
}
}
abstract class kite implements Flyable
{
@Override
public void fly() {
System.out.println("飞呀飞");
}
}
34.接口的多实现与接口的继承性
- String与Integer都是这个样子的
package com.atshangguigu.java;
/*
* 接口的使用
* 1.接口使用interface来进行定义
* 2.Java中,接口和并列是两个结构
* 3.如何定义接口:定义接口之中的成员
* 3.1 JDK7以前:只能定义全局常量和抽象的方法
* 全局常量:public static final,但是书写的时候可以省略
* 抽象方法:public abstract
* 3.2 JDK8以后:除了定义全局常量和抽象的方法,还可以定义静态方法 默认方法
* 4.接口之中是不能定义构造器的!意味着接口是不可以进行实例化的.---跟类去发生关系
* 5.Java开发的过程之中,接口都是通过类去实现(implements),而不是继承.
* 如果实现类覆盖(重写)了接口之中的所有抽象的方法,则此实现类就可以进行实例化
* 如果实现类没有覆盖接口之中所有的抽象方法,则此实现类仍然为一个抽象类
* 6. Java类可以实现多个接口 ---> 弥补了Java单继承性的局限性
* 格式:class A entends B implements C,D,E{}
* 7. 接口与接口之间是可以继承的,而且是多继承
* ***************************************************************************
* 8. 接口的具体使用,体现了多态性的问题
* 9. 接口的本质是一种规范,是一种规则
*
* 面试题:抽象类和接口有什么异同?
*
*
*
*/
public class InterfaceTest {
public static void main(String[] args) {
System.out.println(Flyable.MAX_SPEED);
System.out.println(Flyable.MIN_SPEED);
//Flyable.MIN_APEED = 2.0;
Plane plane = new Plane();
plane.fly();
}
}
interface Flyable
{
//全局常量
public static final int MAX_SPEED = 7000;//第一宇宙速度
int MIN_SPEED = 1;//这里只是对public static final进行省略
//抽象方法
public abstract void fly();
void stop();//省略了public abstract
//构造器
/*public Flyable()
{}*/
}
interface Attackable
{
void attack();
}
class Plane implements Flyable
{
@Override
public void fly() {
System.out.println("通过机翼飞");
}
@Override
public void stop() {
System.out.println("通过降落在地面上,制动停止");
}
}
abstract class kite implements Flyable
{
@Override
public void fly() {
System.out.println("飞呀飞");
}
}
class Bullet extends Object implements Flyable,Attackable
{
@Override
public void attack() {
// TODO Auto-generated method stub
}
@Override
public void fly() {
// TODO Auto-generated method stub
}
@Override
public void stop() {
// TODO Auto-generated method stub
}
}
/**********************************************/
//下面是进行多继承的一个过程
interface AA
{
void method();
}
interface BB
{
void method1();
}
interface CC extends AA,BB
{}
35.实例演示接口是一种规范
- 驱动--规范
- 面向接口编程
package day15;
/*
* 接口的使用
* 1.接口使用上满足多态性
* 2.接口实际上就是定义了一种规范
*/
public class UsbTest {
public static void main(String[] args) {
Computer com = new Computer();
Flash flash = new Flash();
com.transferData(flash);//体现的是
}
}
interface USB
{
//常量:定义了长 宽 最大和最小传输速率
void start();
void stop();
}
class Computer //USB usb = new flash();
{
public void transferData(USB usb)
{
usb.start();
System.out.println("具体的传输细节");
usb.stop();
}
}
class Flash implements USB
{
@Override
public void start() {
System.out.println("U盘开启工作");
}
@Override
public void stop() {
System.out.println("U盘坏了");
}
}
class Printer implements USB
{
@Override
public void start() {
System.out.println("打印机开始工作");
}
@Override
public void stop() {
System.out.println("打印机没有墨水了");
}
}
36.创建接口匿名实现类的对象
package day15;
/*
* 接口的使用
* 1.接口使用上满足多态性
* 2.接口实际上就是定义了一种规范
* 3.开发中提现面向接口编程
*/
public class UsbTest {
public static void main(String[] args) {
Computer com = new Computer();
//1.创建了接口的非匿名实现类的非匿名对象
Flash flash = new Flash();
com.transferData(flash);//体现的是
//2.创建了接口的非匿名实现类的匿名对象
com.transferData(new Printer());
//3.创建接口的匿名实现类的非匿名对象
USB phone = new USB(){
@Override
public void start() {
System.out.println("手机开始工作");
}
@Override
public void stop() {
System.out.println("手机关机");
}};
com.transferData(phone);
//4.创建接口的匿名实现类的匿名对象
com.transferData(new USB(){
@Override
public void start() {
System.out.println("游戏及开始工作");
}
@Override
public void stop() {
System.out.println("游戏机坏了");
}});
}
}
interface USB
{
//常量:定义了长 宽 最大和最小传输速率
void start();
void stop();
}
class Computer //USB usb = new flash();
{
public void transferData(USB usb)
{
usb.start();
System.out.println("具体的传输细节");
usb.stop();
}
}
class Flash implements USB
{
@Override
public void start() {
System.out.println("U盘开启工作");
}
@Override
public void stop() {
System.out.println("U盘坏了");
}
}
class Printer implements USB
{
@Override
public void start() {
System.out.println("打印机开始工作");
}
@Override
public void stop() {
System.out.println("打印机没有墨水了");
}
}
37.接口应用:代理模式
- 这次见叫叔叔,下次见叫叔叔,不用明白其中的原理,时间长了,自然就会叫叔叔了.
- 概念:
代理模式是 Java 开发中使用较多的一种设计模式。代理设计就是为其他对象提供一种代理以控制对这个对象的访问。
-
找房子:自己即是被代理类;中介就是代理类;就是跟明星或者经纪人一样.
package com.atshangguigu.java;
/*
* 接口的应用:代理模式
*/
public class NetWorkTest {
public static void main(String[] args) {
Server server = new Server();
ProxyServer proxyServer = new ProxyServer(server);
proxyServer.browse();
}
}
interface NetWork
{
public void browse();
}
//被代理类
class Server implements NetWork
{
@Override
public void browse() {
System.out.println("真实的服务器访问网络");
}
}
//代理类
class ProxyServer implements NetWork
{
private NetWork work;
public ProxyServer(NetWork work)
{
this.work = work;
}
public void check()
{
System.out.println("检查网络状态");
}
@Override
public void browse() {
check();
work.browse();
}
}
- 每针对一种接口一种代理类
package com.atshangguigu.java;
public class StaticProxyTest {
public static void main(String[] args) {
Star s = new Proxy(new RealStar());
s.confer();
s.signContract();
s.bookTicket();
s.sing();
s.collectMoney();
}
}
interface Star {
void confer();// 面谈
void signContract();// 签合同
void bookTicket();// 订票
void sing();// 唱歌
void collectMoney();// 收钱
}
//被代理类
class RealStar implements Star {
public void confer() {
}
public void signContract() {
}
public void bookTicket() {
}
public void sing() {
System.out.println("明星:歌唱~~~");
}
public void collectMoney() {
}
}
//代理类
class Proxy implements Star {
private Star real;
public Proxy(Star real) {
this.real = real;
}
public void confer() {
System.out.println("经纪人面谈");
}
public void signContract() {
System.out.println("经纪人签合同");
}
public void bookTicket() {
System.out.println("经纪人订票");
}
public void sing() {
real.sing();
}
public void collectMoney() {
System.out.println("经纪人收钱");
}
}
38.接口应用:工厂模式
- 工厂模式:实现了创建者与调用者的分离,即将创建对象的具体过程屏蔽隔离 起来,达到提高灵活性的目的。
1.无工厂模式(复制)
package com.atguigu.pattern.factory.nofactory;
interface Car{
void run();
}
class Audi implements Car{
public void run() {
System.out.println("奥迪在跑");
}
}
class BYD implements Car{
public void run() {
System.out.println("比亚迪在跑");
}
}
public class Client01 {
public static void main(String[] args) {
Car a = new Audi();
Car b = new BYD();
a.run();
b.run();
}
}
2.简单工厂模式 缺点:对于增加新产品,不修改代码的话,是无法扩展的。违反了开闭原则(对 扩展开放;对修改封闭)。
package com.atguigu.pattern.factory.simple;
interface Car {
void run();
}
class Audi implements Car {
public void run() {
System.out.println("奥迪在跑");
}
}
class BYD implements Car {
public void run() {
System.out.println("比亚迪在跑");
}
}
//工厂类
class CarFactory {
//方式一
public static Car getCar(String type) {
if ("奥迪".equals(type)) {
return new Audi();
} else if ("比亚迪".equals(type)) {
return new BYD();
} else {
return null;
}
}
//方式二
// public static Car getAudi() {
// return new Audi();
// }
//
// public static Car getByd() {
// return new BYD();
// }
}
public class Client02 {
public static void main(String[] args) {
Car a = CarFactory.getCar("奥迪");
a.run();
Car b = CarFactory.getCar("比亚迪");
b.run();
}
}
3.工厂方法模式
package com.atguigu.pattern.factory.method;
interface Car{
void run();
}
//两个实现类
class Audi implements Car{
public void run() {
System.out.println("奥迪在跑");
}
}
class BYD implements Car{
public void run() {
System.out.println("比亚迪在跑");
}
}
//工厂接口
interface Factory{
Car getCar();
}
//两个工厂类
class AudiFactory implements Factory{
public Audi getCar(){
return new Audi();
}
}
class BydFactory implements Factory{
public BYD getCar(){
return new BYD();
}
}
public class Client {
public static void main(String[] args) {
Car a = new AudiFactory().getCar();
Car b = new BydFactory().getCar();
a.run();
b.run();
}
}
4.抽象工厂模式:抽象工厂模式和工厂方法模式的区别就在于需要创建对象的复杂程度上。
39.接口课后两道笔试题
- 上面的这道题之中的Systemout.println(x);是有歧义的.因为父类与接口之中都是有x的.父类和 接口是视为同一条线上的.上面如果要是想要调用父类之中的x,其代码应改为 Sysout.out.println(super.x);如果要是想要调用接口之中的那么应该改为 Sysout.out.println(A.x);
- 上面的接口之中的Public Static final Ball ball = new ball('PingPang");有省略.
40.接口练习:比较对象的大小
41.Java8接口的新特性
- CompareA.java
package com.atshangguigu.exer1;
/*
* jdk8之中除了可以定义全局常量和抽象方法之外,还可以定义静态方法与默认方法
*/
public interface CompareA {
//静态方法---直接通过接口进行调用
public static void method1()
{
System.out.println("Compare:西安");
}
//默认方法---通过实现类
public default void method2()
{
System.out.println("Compare:天津");
}
default void method3()
{
System.out.println("Compare:沧州");
}
}
- CompareB.java
package com.atshangguigu.exer1;
public interface CompareB {
default void method3()
{
System.out.println("CompareB:天大");
}
}
- SuperClassTest1.java
package com.atshangguigu.exer1;
public class SuperClassTest1 {
public void method3()
{
System.out.println("SuperCompare:河北");
}
}
- SuperClass.java
package com.atshangguigu.exer1;
public class SubClass {
public static void main(String[] args) {
SubClassTest s = new SubClassTest();
//s.method1();//完全无视接口之中的静态的方法
//知识点1:接口之中的静态的方法,只能通过接口去进行调用
CompareA.method1();
//知识点2:可以通过类的对象进行调用接口之中的默认方法,或者进行重写.不可以使用类调用
//如果实现类重写了接口之中的默认方法,调用的时候,仍然调用的是重写之后的方法
s.method2();
//知识点3:如果子类(或者实现类)继承的父类和实现的接口之中声明了同名同参数的方法,
//那么子类在没有重写这个方法的情况之下,默认调用的是父类之中的方法同名同参数的方法---类优先原则
//上述只是针对类而已,不针对于属性
s.method3();
//知识点4:如果实现类实现了多个接口,定义了同名同参数的默认方法.
//那么在实现类没有重写此方法的情况下,报错.----这种情况是接口冲突的现象.
//这就需要我们在类之中必须重写此方法
}
}
class SubClassTest extends SuperClassTest1 implements CompareA,CompareB
{
public void method2()
{
System.out.println("SubCompare:河北省");
}
public void method3()
{
System.out.println("SubCompare:河北省");
}
//知识点5:如何调用在子类或者实现类方法之中调用父类 接口中被重写的方法
public void myMethod()
{
method3();//调用自己的
super.method3();//调用父类之中的
CompareA.super.method3();
CompareB.super.method3();
}
}
42.java8接口新特性的应用
- 这个就是对上面的进行补充的一个过程. 视频上讲的很有趣,这里就没有重写代码.
43.内部类的分类
- 人和大脑的关系,大脑是一个内部类,人是一个外部类.
package com.atshangguigu.java2;
/*
* 类的内部成员之五:内部类
* 1.Java中允许将一个类A声明在另一个类B之中,那么说类A就是内部类,类B就是外部类
* 2.内部类的分类:成员内部类(静态和非静态) pk 局部内部类(方法内,代码块内,构造器内)
*
*/
public class InnerClass {
}
class Person
{
//非静态成员内部类
class Dog
{
}
//静态成员内部类
static class Cat
{
}
public void method()
{
//局部内部类
class A
{
}
}
{
class B
{}
}
public Person()
{
class C
{}
}
}
44.成员内部类的特点
package com.atshangguigu.java2;
/*
* 类的内部成员之五:内部类
* 1.Java中允许将一个类A声明在另一个类B之中,那么说类A就是内部类,类B就是外部类
* 2.内部类的分类:成员内部类(静态和非静态) pk 局部内部类(方法内,代码块内,构造器内)
* 3.成员内部类:
* 一方面:作为外部类的成员:
* (1)可以调用外部类的一个结构
* (2)可以被abstract修饰
* (3)可以被四种权限进行修饰
* 另一方面:作为一个类出现:
* (1)类内可以定义属性 方法 构造器等---套娃
* (2)可以使用final修饰,表示此类是不可以被继承的,言外之意是不是用final是可以被继承的
* (3)可以被abstract修饰,不能被实例化
*/
public class InnerClass {
}
class Person
{
String name;
int age;
public void eat()
{
System.out.println("人是可以恰饭");
}
//非静态成员内部类
class Dog
{
String name;
public void shot()
{
System.out.println("马晓栋是我儿子");
Person.this.eat();//调用外部类的属性
}
public Dog()
{
}
}
//静态成员内部类
static class Cat
{
String name;
int age;
public void show()
{
System.out.println("喵喵");
}
public Cat()
{}
//eat();
}
public void method()
{
//局部内部类
class A
{
}
}
{
class B
{}
}
public Person()
{
class C
{}
}
}
45.如何实例化成员内部类
package com.atshangguigu.java2;
/*
* 类的内部成员之五:内部类
* 1.Java中允许将一个类A声明在另一个类B之中,那么说类A就是内部类,类B就是外部类
* 2.内部类的分类:成员内部类(静态和非静态) pk 局部内部类(方法内,代码块内,构造器内)
* 3.成员内部类:
* 一方面:作为外部类的成员:
* (1)可以调用外部类的一个结构
* (2)可以被abstract修饰
* (3)可以被四种权限进行修饰
* 另一方面:作为一个类出现:
* (1)类内可以定义属性 方法 构造器等---套娃
* (2)可以使用final修饰,表示此类是不可以被继承的,言外之意是不是用final是可以被继承的
* (3)可以被abstract修饰,不能被实例化
* 4.关注如下的三个问题
* 4.1如何实例化成员内部类的对象
* 4.2如何在成员内部类之中区分调用外部类的结构
* 4.3开发当中局部内部类的使用
*/
public class InnerClass {
public static void main(String[] args) {
//创建Dog实例(静态的成员内部类)
Person.Cat cat = new Person.Cat();
cat.show();
//创建Cat实例(非静态成员内部类)
Person p = new Person();
Person.Dog dog = p.new Dog();
dog.shot();
}
}
class Person
{
String name;
int age;
public void eat()
{
System.out.println("人是可以恰饭");
}
//非静态成员内部类
class Dog
{
String name;
public void shot()
{
System.out.println("马晓栋是我儿子");
Person.this.eat();//调用外部类的属性
}
public Dog()
{
}
}
//静态成员内部类
static class Cat
{
String name;
int age;
public void show()
{
System.out.println("喵喵");
}
public Cat()
{}
//eat();
}
public void method()
{
//局部内部类
class A
{
}
}
{
class B
{}
}
public Person()
{
class C
{}
}
}
46.成员内部类中调用外部类的结构
package com.atshangguigu.java2;
/*
* 类的内部成员之五:内部类
* 1.Java中允许将一个类A声明在另一个类B之中,那么说类A就是内部类,类B就是外部类
* 2.内部类的分类:成员内部类(静态和非静态) pk 局部内部类(方法内,代码块内,构造器内)
* 3.成员内部类:
* 一方面:作为外部类的成员:
* (1)可以调用外部类的一个结构
* (2)可以被abstract修饰
* (3)可以被四种权限进行修饰
* 另一方面:作为一个类出现:
* (1)类内可以定义属性 方法 构造器等---套娃
* (2)可以使用final修饰,表示此类是不可以被继承的,言外之意是不是用final是可以被继承的
* (3)可以被abstract修饰,不能被实例化
* 4.关注如下的三个问题
* 4.1如何实例化成员内部类的对象
* 4.2如何在成员内部类之中区分调用外部类的结构
* 4.3开发当中局部内部类的使用
*/
public class InnerClass {
public static void main(String[] args) {
//创建Dog实例(静态的成员内部类)
Person.Cat cat = new Person.Cat();
cat.show();
//创建Cat实例(非静态成员内部类)
Person p = new Person();
Person.Dog dog = p.new Dog();
dog.shot();
System.out.println("***********************************");
dog.display("小栋");
}
}
class Person
{
String name = "小田田";
int age;
public void eat()
{
System.out.println("人是可以恰饭");
}
//非静态成员内部类
class Dog
{
String name = "大黄";
public void shot()
{
System.out.println("看,小栋");
Person.this.eat();//调用外部类的属性
System.out.println(age);//这是没有重名的情况
}
public void display(String name)
{
System.out.println(name);//方法形参之中的
System.out.println(this.name);//内部类的属性
System.out.println(Person.this.name);//外部类的属性
}
public Dog()
{
}
}
//静态成员内部类
static class Cat
{
String name;
int age;
public void show()
{
System.out.println("喵喵");
}
public Cat()
{}
//eat();
}
public void method()
{
//局部内部类
class A
{
}
}
{
class B
{}
}
public Person()
{
class C
{}
}
}
47.局部内部类的使用
package com.atshangguigu.java2;
/*
* 开发之中的局部内部类的使用
*/
public class InnerClassTest1 {
//在开发的过程之中是很少见的
public void method()
{
//局部内部类
class AA
{}
}
//方法的作用是返回一个实现了Comparable接口类的对象
public Comparable getComparable()
{
//创建一个实现了Comparable的接口一个类:局部内部类
//方式一:
/*
class MyComparable implements Comparable
{
@Override
public int compareTo(Object o) {
return 0;
}
}
return new Comparable();
*/
//方式二:
return new Comparable()
{
@Override
public int compareTo(Object o) {
// TODO Auto-generated method stub
return 0;
}
}
}
}
48.每日一考
- abstract能够修饰哪些结构?修饰以后,有什么特点?
答:修饰类和方法;类不能够进行实例化,提供子类(重写);abstract修饰的方法所属的类必须是抽象类,抽象方法只定义了一种功能的标准.具体的执行需要子类去实现.
- 接口能否继承接口?(能)抽象类能够实现(implements)接口?(能)抽象的类能否继承非抽象的类?(能)