1 MS-DOS命令提示符
2 IDEA快捷键
3 JAVA开发环境
3.1 JVM
JVM(Java Virtual Machine ):Java虚拟机,简称JVM,是运行所有Java程序的假想计算机,是Java程序的 运行环境,是Java 最具吸引力的特性之一。我们编写的Java代码,都运行在 JVM 之上。
跨平台:任何软件的运行,都必须要运行在操作系统之上,而我们用Java编写的软件可以运行在任何的操作系 统上,这个特性称为Java语言的跨平台特性。该特性是由JVM实现的,我们编写的程序运行在JVM上,而JVM 运行在操作系统上。
如图,JAVA虚拟机本身不具备跨平台的功能,每个操作系统下都有不同版本的虚拟机
3.2 JRE和JDK
JRE (Java Runtime Environment) :是Java程序的运行时环境,包含 JVM 和运行时所需要的 核心类库 。
JDK (Java Development Kit):是Java程序开发工具包,包含 JRE 和开发人员使用的工具。
我们想要运行一个已有的Java程序,那么只需安装 JRE 即可。
我们想要开发一个全新的Java程序,那么必须安装 JDK 。
三者关系: JDK > JRE > JVM
4 JAVA基本知识
4.1 数据类型分类
Java的数据类型分为两大类:
基本数据类型:包括 整数 、 浮点数 、 字符 、 布尔 。
引用数据类型:包括 类 、 数组 、 接口 。
四类八种基本数据类型:
4.2 数据类型转换
范围小的类型向范围大的类型提升
byte、short、char‐‐>int‐‐>long‐‐>float‐‐>double
4.3 JAVA虚拟机内存划分
5 数组
数组就是存储数据长度固定的容器,保证多个数据的数据类型要一致。
5.1 格式
- 数组存储的数据类型[] 数组名字 = new 数组存储的数据类型[长度];
- 数据类型[] 数组名 = new 数据类型[]{元素1,元素2,元素3…};
- 数据类型[] 数组名 = {元素1,元素2,元素3…} ;
5.2 注意事项
- 不能越界,否则报错
- 数组空指针异常
5.3 数组作为方法参数和返回值
- 数组作为方法参数传递,传递的参数是数组内存的地址。
- 数组作为方法的返回值,返回的是数组的内存地址
6 类
- 定义类:就是定义类的成员,包括成员变量和成员方法。
- 成员变量:和以前定义变量几乎是一样的。只不过位置发生了改变。在类中,方法外。
- 成员方法:和以前定义方法几乎是一样的。只不过把static去掉。
6.1 成员变量默认值
6.2 一个对象的内存图
6.3 两个对象使用同一个方法内存图
6.4 两个引用指向同一个对象的内存图
6.5 成员变量和局部变量区别
在类中的位置不同
- 成员变量:类中,方法外
- 局部变量:方法中或者方法声明上(形式参数)
作用范围不一样
- 成员变量:类中
- 局部变量:方法中
初始化值的不同
- 成员变量:有默认值
- 局部变量:没有默认值。必须先定义,赋值,最后使用
在内存中的位置不同
- 成员变量:堆内存
- 局部变量:栈内存
生命周期不同 了解
- 成员变量:随着对象的创建而存在,随着对象的消失而消失
- 局部变量:随着方法的调用而存在,随着方法的调用完毕而消失
7 封装
将属性隐藏起来,若需要访问某个属性,提供公共方法对其访问。
7.1 步骤
- 使用 private 关键字来修饰成员变量。 被private修饰后的成员变量和成员方法,只在本类中才能访问。
- 对需要访问的成员变量,提供对应的一对 getXxx 方法 、 setXxx 方法。
7.2 封装优化
7.2.1 this
this代表所在类的当前对象的引用(地址值),即对象自己的引用。
记住 :方法被哪个对象调用,方法中的this就代表那个对象。即谁在调用,this就代表谁。
7.2.2 构造方法
当一个对象被创建时候,构造方法用来初始化该对象,给对象的成员变量赋初始值。
无论你与否自定义构造方法,所有的类都有构造方法,因为Java自动提供了一个无参数构造方法, 一旦自己定义了构造方法,Java自动提供的默认无参数构造方法就会失效。
一个例子:
public class Student {
private String name;
private int age;
public Student() {}
public Student(String name,int age) {
this.name = name;
this.age = age;
}
}
注意事项:
- 如果你不提供构造方法,系统会给出无参数构造方法。
- 如果你提供了构造方法,系统将不再提供无参数构造方法。
- 构造方法是可以重载的,既可以定义参数,也可以不定义参数。
7.3 标准规范JavaBean
public class ClassName{
}
8 API
API(Application Programming Interface),应用程序编程接口
9 Scanner类
一个可以解析基本类型和字符串的简单文本扫描器。 例如,以下代码使用户能够从 System.in 中读取一个数。
System.in 系统输入指的是通过键盘录入数据。
9.1 使用步骤
导包
import java.util.Scanner;
创建对象
Scanner sc = new Scanner(System.in);
调用方法
int i = sc.nextInt(); // 接收一个键盘录入的整数
10 匿名对象
创建对象时,只有创建对象的语句,却没有把对象地址值赋值给某个变量。
注意:
- 创建匿名对象直接调用方法,没有变量名。
- 一旦调用两次方法,就是创建了两个对象,造成浪费。
- 匿名对象可以作为方法的参数和返回值 。
11 Random类
此类的实例用于生成伪随机数。
11.1 使用步骤
导包
import java.util.Random;
创建对象
Random r = new Random();
11.2 成员方法
public int nextInt(int n) :返回一个伪随机数,范围在 0 (包括)和 指定值 n (不包括)之间的 int 值。
12 ArrayList类
数组的长度是固定的,无法适应数据变化的需 求。为了解决这个问题,Java提供了另一个容器 java.util.ArrayList 集合类,让我们可以更便捷的存储和操作对象数据。
java.util.ArrayList 是大小可变的数组的实现,存储在内的数据称为元素。此类提供一些方法来操作内部存储 的元素。 ArrayList 中可不断添加元素,其大小也自动增长。
12.1 使用方法
导包
import java.util.ArrayList;
创建对象
ArrayList list = new ArrayList<>();
12.2 成员方法
- public boolean add(E e) :将指定的元素添加到此集合的尾部。
- public E remove(int index) :移除此集合中指定位置上的元素。返回被删除的元素。
- public E get(int index) :返回此集合中指定位置上的元素。返回获取的元素。
- public int size() :返回此集合中的元素数。遍历集合时,可以控制索引范围,防止越界。
12.3 如何存储基本数据类型
ArrayList对象不能存储基本类型,只能存储引用类型的数据。类似 不能写,但是存储基本数据类型对应的 包装类型是可以的。
基本类型 | 基本类型包装类 |
---|
byte | Byte | short | Short | int | Integer | long | Long | float | Float | double | Double | char | Character | boolean | Bootlean |
13 String类
13.1 特点
- 字符串不变:字符串的值在创建后不能被更改。
- 因为String对象是不可变的,所以它们可以被共享。
- “abc” 等效于 char[] data={ ‘a’ , ‘b’ , ‘c’ } 。
13.2 构造方法
- public String() :初始化新创建的 String对象,以使其表示空字符序列。
- public String(char[] value) :通过当前参数中的字符数组来构造新的String。
- public String(byte[] bytes) :通过使用平台的默认字符集解码当前参数中的字节数组来构造新的 String。
13.3 常用方法
以下两种都返回布尔值:
- public boolean equals (Object anObject) :将此字符串与指定对象进行比较。
- public boolean equalsIgnoreCase (String anotherString) :将此字符串与指定对象进行比较,忽略大小写。
*equals方法:推荐常量写前面,变量写后面,例如:“abc”.equals(str1) ,因为str1为空倒过来回报错
13.4 常用功能方法
- public int length () :返回此字符串的长度。
- public String concat (String str) :将指定的字符串连接到该字符串的末尾。
- public char charAt (int index) :返回指定索引处的 char值。
- public int indexOf (String str) :返回指定子字符串第一次出现在该字符串内的索引。
- public String substring (int beginIndex) :返回一个子字符串,从beginIndex开始截取字符串到字符 串结尾。
- public String substring (int beginIndex, int endIndex) :返回一个子字符串,从beginIndex到 endIndex截取字符串。含beginIndex,不含endIndex。
13.5 转换功能方法
- public char[] toCharArray () :将此字符串转换为新的字符数组。
- public byte[] getBytes () :使用平台的默认字符集将该 String编码转换为新的字节数组。
- public String replace (CharSequence target, CharSequence replacement) :将与target匹配的字符串使 用replacement字符串替换。
13.6 分割功能方法
public String[] split(String regex) :将此字符串按照给定的regex(规则)拆分为字符串数组。
*split方法:如果用.切分则需要写"\."
13.7 内存图
1、对于引用类型来说,==进行的是地址值的比较。 2、双引号直接写的字符串在常量池当中,new的不在池当中。
14 Static关键字
推荐用类名调用静态方法,不推荐用对象名调用
14.1 类变量(一个例子)
当 static 修饰成员变量时,该变量称为类变量。该类的每个对象都共享同一个类变量的值。任何对象都可以更改 该类变量的值,但也可以在不创建该类的对象的情况下对类变量进行操作。
public class Student {
private String name;
private int age;
private int sid;
public static int numberOfStudent = 0;
public Student(String name, int age){
this.name = name;
this.age = age;
this.sid = ++numberOfStudent;
}
public void show() {
System.out.println("Student : name=" + name + ", age=" + age + ", sid=" + sid );
}
}
public class StuDemo {
public static void main(String[] args) {
Student s1 = new Student("张三", 23);
Student s2 = new Student("李四", 24);
Student s3 = new Student("王五", 25);
Student s4 = new Student("赵六", 26);
s1.show();
s2.show();
s3.show();
s4.show();
}
}
14.2 静态方法
当 static 修饰成员方法时,该方法称为类方法 。静态方法在声明中有 static ,建议使用类名来调用,而不需要创建类的对象。调用方式非常简单。
注意事项:
- 静态方法可以直接访问类变量和静态方法。
- 静态方法不能直接访问普通成员变量或成员方法。反之,成员方法可以直接访问类变量或静态方法。 静态方法只能访问静态成员。
- 静态方法中,不能使用this关键字。
14.3 内存图
静态代码块:
15 Array类
java.util.Arrays 此类包含用来操作数组的各种方法,比如排序和搜索等。其所有方法均为静态方法,调用起来 非常简单。
15.1 操作数组的方法
- public static String toString(int[] a) :返回指定数组内容的字符串表示形式。
- public static void sort(int[] a) :对指定的 int 型数组按数字升序进行排序。
16 Math类
java.lang.Math 类包含用于执行基本数学运算的方法,如初等指数、对数、平方根和三角函数。类似这样的工具 类,其所有方法均为静态方法,并且不会创建对象,调用起来非常简单。
16.1 基本运算方法
- public static double abs(double a) :返回 double 值的绝对值。
- public static double ceil(double a) :返回大于等于参数的最小的整数。
- public static double floor(double a) :返回小于等于参数最大的整数。
- public static long round(double a) :返回最接近参数的 long。(相当于四舍五入方法)
17 继承
直接通过子类对象访问成员变量(num):等号左边是谁,就优先用谁,没有则向上找。
间接通过成员方法访问成员变量(methodFu() methodZi()):该方法属于谁,就优先用谁,没有则向上找。
在父子类的继承关系当中,创建子类对象,访问成员方法(method())的规则:创建的对象是谁,就优先用谁,如果没有则向上找。
17.1 重写
重写(Override):方法的名称一样,参数列表【也一样】。覆盖、覆写。
重载(Overload):方法的名称一样,参数列表【不一样】。
Tips:重写的时候用上@Override 会有系统检查,避免小手一抖写错重写
注意事项:
方法覆盖重写的注意事项:
-
必须保证父子类之间方法的名称相同,参数列表也相同。 @Override:写在方法前面,用来检测是不是有效的正确覆盖重写。这个注解就算不写,只要满足要求,也是正确的方法覆盖重写。 -
子类方法的返回值必须【小于等于】父类方法的返回值范围。 小扩展提示:java.Lang . Object类是所有类的公共最高父类(祖宗类),java.lang.String就是object的子类。 -
子类方法的权限必须【大于等于】父类方法的权限修饰符。小扩展提示:public > protected > (default) > private备注:(default)不是关键字default,而是什么都不写,留空。
17.2 父子类构造方法
继承关系中,父子类构造方法的访问特点:
- 子类构造方法当中有一个默认隐含的“super()"调用,所以一定是先调用的父类构造,后执行的子类构造。
- 子类构造可以通过super关键字来调用父类重载构造。
- super的父类构造调用,必须是子类构造方法的第一个语句。不能一个子类构造调用多次super构造。
总结:子类必须调用父类构造方法,不写则赠送super();写了则用写的指定的super调用,super只能有一个.还必须是第一个。
17.3 super三种用法(访问父类)
- 在子类的成员方法中,访问父类的成员变量。
- 在子类的成员方法中,访问父类的成员方法。
- 在子类的构造方法中,访问父类的构造方法。public Zi(){super();}
17.4 this三种方法(访问本类)
- 在本类的成员方法中,访问本类的成员变量。
- 在本类的成员方法中,访问本类的另—个成员方法。
- 在本类的构造方法中,访问本类的另一个构造方法。
在第三种用法当中要注意:
A. this ( …)调用也必须是构造方法的第一个语句,唯一一个。
B.super和this两种构造调用,不能同时使用。
17.5 super和this内存图
18 抽象类
抽象方法:就是加上abstract关键字,然后去掉大括号,直接分号结束。
抽象类:抽象方法所在的类,必须是抽象类才行。在class之前写上abstract即可。
如何使用抽象类和抽象方法:
1.不能直接创建new抽象类对象。
2.必须用一个子类来继承抽象父类。
3.子类必须覆盖重写抽象父类当中所有的抽象方法。
覆盖重写(实现):子类去掉抽象方法的abstract关键字,然后补上方法体大括号。
4.创建子类对象进行使用。
19 微信发红包案例(?)
用户类
public class User {
private String username;
private double leftMoney;
public User() {
}
public User(String username, double leftMoney) {
this.username = username;
this.leftMoney = leftMoney;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public double getLeftMoney() {
return leftMoney;
}
public void setLeftMoney(double leftMoney) {
this.leftMoney = leftMoney;
}
public void show() {
System.out.println("用户名:"+ username +" , 余额为:" + leftMoney + "元");
}
}
群主类
public class QunZhu extends User {
public QunZhu() {
}
public QunZhu(String username, double leftMoney) {
super(username, leftMoney);
}
public ArrayList<Double> send(int money, int count) {
double leftMoney = getLeftMoney();
if(money > leftMoney) {
return null;
}
setLeftMoney(leftMoney ‐ money);
ArrayList<Double> list = new ArrayList<>();
money = money * 100;
int m = money / count;
int l = money % count;
for (int i = 0; i < count ‐ 1; i++) {
list.add(m / 100.0);
}
if (l == 0) {
list.add(m / 100.0);
} else {
list.add((m + l) / 100.00);
}
return list;
}
}
成员类
public class Member extends User {
public Member() {
}
public Member(String username, double leftMoney) {
super(username, leftMoney);
}
public void openHongbao(ArrayList<Double> list) {
Random r = new Random();
int index = r.nextInt(list.size());
Double money = list.remove(index);
setLeftMoney( money );
}
}
测试类
public class Test {
public static void main(String[] args) {
QunZhu qz = new QunZhu("群主" , 200);
Scanner sc = new Scanner();
System.out.println("请输入金额:");
int money = sc.nextInt();
System.out.println("请输入个数:");
int count = sc.nextInt();
ArrayList<Double> sendList = s.send(money,count);
if(sendList == null){
System.out.println(" 余额不足...");
return;
}
Member m = new Member();
Member m2 = new Member();
Member m3 = new Member();
m.openHongbao(sendList);
m2.openHongbao(sendList);
m3.openHongbao(sendList);
qz.show();
m.show();
m2.show();
m3.show();
}
}
20 接口
20.1 抽象方法abstract
一定要覆盖重写,否则报错。
通过实现类的对象来调用。
不用写方法体。
20.2 默认方法default
假设有一个很大很大的项目,一个接口被很多很多的类所实现,大家都平安无事平稳地运行着。突然有一天,出现了一个小小地问题,或者说有一个更好的优化方案,需要在这些实现类去增加。在默认方法出现之前,只有抽象方法,且需要在实现类中给出具体定义才能操作,那岂不是只能两眼一闭,直接从早干到晚地添加啦。 但是,默认方法地出现允许在接口中给出方法的具体实现,且实现类中能够自动实现默认方法,我只需要将这个优化放在接口的默认方法里面,就能完成对所有实现类的优化啦。
可覆盖重写也可以不, 二选一。
但是只能通过实现类的对象来调用。
要写方法体。
20.3 静态方法static
在没有新增静态方法之前,我们如果想让一些固定的操作在接口中出现,就必须定义一个和接口配套的实现类。而接口中静态方法的出现,可以直接通过接口调用静态方法。
就很直接地在接口中定义静态方法,且可以被接口直接调用,不需要再定义与其配套的实现类,多舒服哦。
不能在实现类里重写静态方法。
不能通过接口实现类的对象来调用接口当中的静态方法。 一定要通过接口名称直接调用其中的静态方法。
要写方法体。
20.4 私有方法private
问题背景:我们需要抽取一个公共方法,用来解决默认方法之间重复代码的问题。但这个共有方法不应该让实现类使用,应该是私有化的。
1.普通私有方法,解决多个默认方法之间重复代码问题格式:
private 返回值类型 方法名称(参数列表){
方法体
}
2.静态私有方法,解决多个静态方法之间重复代码问题格式:
private static 返回值类型 方法名称(参数列表){
方法体
}
20.5 接口常量
接口当中也可以定义“成员变量”,但是必须使用public static final三个关键字进行修饰。
从效果上看,这其实就是接口的【常量】。
格式:
public static final 数据类型常量名称 = 数据值 ;
备注:
—旦使用final关键字进行修饰,说明不可改变。
注意事项: 1.接口当中的常量,可以省略public static final,注意:不写也照样是这样。
2.接口当中的常量,必须进行赋值;不能不赋值。
3.接口中常量的名称,使用完全大写的字母,用下划线进行分隔。(推荐命名规则)
20.6 接口注意事项
1.接口是没有静态代码块或者构造方法的。
2.一个类的直接父类是唯一的,但是一个类可以同时实现多个接口。
格式:
public class MyInterfaceImpl implements MyInterfaceA,MyInterfaceB {/覆盖重写所有抽象方法
}
3.如果实现类所实现的多个接口当中,存在重复的抽象方法,那么只需要覆盖重写一次即可。
4.如果实现类没有覆盖重写所有接口当中的所有抽象方法,那么实现类就必须是一个抽象类。
5.如果实现类锁实现的多个接口当中,存在重复的默认方法,那么实现类一定要对冲突的默认方法进行覆盖重写。
6.一个类如果直接父类当中的方法,和接口当中的默认方法产生了冲突,优先用父类当中的方法。
20.7 接口多继承
1.类与类之间是单继承的。直接父类只有一个。
2.类与接口之间是多实现的。一个类可以实现多个接口。
3.接口与接口之间是多继承的。
注意事项:
1、多个父接口当中的抽象方法如果重复,没关系。 2、多个父接口当中的默认方法如果重复,那么子接口必须进行默认方法的覆盖重写【而且带着default关键字】
子接口重写默认方法时,default关键字可以保留。
子类重写默认方法时,default关键字不可以保留。
21 多态性
21.1 成员方法
因为方法覆盖重写,所以调用的是重写后的Zi的method(),此时方法看等号右边。
编译看左边,运行看右边。
Fu obj = new Zi();
obj.method();
21.2 成员变量
不会覆盖重写,所以要看等号左边是谁,优先用谁,没有则向上找。
编译看左边,运行还看左边。
Fu obj = new Zi();
sout(obj.num);
多态性的优势:https://www.cnblogs.com/lv-suma/p/12842575.html
由于多态特性的支持,showAnimalEat方法的Animal类型,是Cat和Dog的父类类型,父类类型接收子类对象,当 然可以把Cat对象和Dog对象,传递给方法。
当eat方法执行时,多态规定,执行的是子类重写的方法,那么效果自然与showCatEat、showDogEat方法一致, 所以showAnimalEat完全可以替代以上两方法。
不仅仅是替代,在扩展性方面,无论之后再多的子类出现,我们都不需要编写showXxxEat方法了,直接使用 showAnimalEat都可以完成。
所以,多态的好处,体现在,可以使程序编写的更简单,并有良好的扩展。
21.3 对象向上转型
21.4 对象向下转型
向上转型一定是安全的,没有问题的,正确的。但是也有一个弊端:对象一旦向上转型为父类,那么就无法调用子类原本特有的内容。
解决方案:用对象的向下转型还原。
21.5 instanceof
变量名 instanceof 数据类型
如果变量属于该数据类型,返回true。
如果变量不属于该数据类型,返回false。
22 笔记本电脑案例(?)
笔记本电脑(laptop)通常具备使用USB设备的功能。在生产时,笔记本都预留了可以插入USB设备的USB接口,但具体是什么USB设备,笔记本厂商并不关心,只要符合USB规格的设备都可以。
定义USB接口,具备最基本的开启功能和关闭功能。鼠标和键盘要想能在电脑上使用,那么鼠标和键盘也必须遵守 USB规范,实现USB接口,否则鼠标和键盘的生产出来也无法使用。
USB类
package cn.itcast.day08.demo06;
public interface USB {
void open();
void close();
}
键盘类
package cn.itcast.day08.demo06;
public class KeyBoard implements USB {
@Override
public void open() {
System.out.println("键盘开启,绿灯闪一闪。");
}
@Override
public void close() {
System.out.println("键盘关闭,绿灯熄灭.");
}
public void click(){
System.out.println("键盘敲击。");
}
}
鼠标类
package cn.itcast.day08.demo06;
public class Mouse implements USB {
@Override
public void open() {
System.out.println("鼠标开启,红灯闪一闪。");
}
@Override
public void close() {
System.out.println("鼠标关闭,红灯熄灭。");
}
public void click(){
System.out.println("鼠标单击。");
}
}
计算机类
package cn.itcast.day08.demo06;
public class Lap{
public void powerOn(){
System.out.println("开机!");
}
public void powerOff(){
System.out.println("关机!");
}
public void useDevice(USB usb){
if(usb!= null){
usb.open();
if(usb instanceof Mouse){
Mouse m = (Mouse) usb;
m.click();
}else if(usb instanceof KeyBoard){
KeyBoard k = (KeyBoard) usb;
k.click();
}
usb.close();
}
}
}
测试类
package cn.itcast.day08.demo06;
public class Demo01 {
public static void main(String[] args) {
Lap lt = new Lap();
lt.powerOn();
USB u = new Mouse();
lt.useDevice(u);
KeyBoard kb = new KeyBoard();
lt.useDevice(kb);
lt.powerOff();
}
}
23 final
23.1 类
public final class 类名 {
}
查询API发现像 public final class String 、 public final class Math 、 public final class Scanner 等,很多我们学习过的类,都是被final修饰的,目的就是供我们使用,而不让我们所以改变其内容。
23.2 方法
修饰符 final 返回值类型 方法名(参数列表){
}
重写被 final 修饰的方法,编译时就会报错。
23.3 局部变量
21.3.1 基本类型
被final修饰后,只能赋值一次,不能再更改
变量当中的数据不可改变
21.3.2 引用类型
引用类型的局部变量,被final修饰后,只能指向一个对象 ,地址值不可改变,但是不影响对象内部的成员变量值的修改 。
23.4 成员变量
成员变量具有默认值所以用了final之后必须手动赋值,不会再给默认值。
对于final的成员变量,要么使用直接赋值,要么通过构造方法赋值。
必须保证类当中所有重载的构造方法,都最终会对final的成员变量进行赋值。
被final修饰的常量名称,一般都有书写规范,所有字母都大写。
24 四种权限修饰符
public:公共的
protected:受保护的
default:默认的
private:私有的
编写代码时,如果没有特殊的考虑,建议这样使用权限:
- 成员变量使用 private ,隐藏细节。
- 构造方法使用 public ,方便创建对象。
- 成员方法使用 public ,方便调用方法。
小贴士:不加权限修饰符,其访问能力与default修饰符相同
25 内部类
将一个类A定义在另一个类B里面,里面的那个类A就称为内部类,B则称为外部类。
访问特点:
- 内部类可以直接访问外部类的成员,包括私有成员。
- 外部类要访问内部类的成员,必须要建立内部类的对象。
访问方式:
- 间接方式:在外部类方法中,使用内部类,然后main只调用外部类的方法。
- 直接方式: 外部类名.内部类名 对象名 = new 外部类型().new 内部类型();
内部类仍然是一个独立的类,在编译之后会内部类会被编译成独立的.class文件,但是前面冠以外部类的类名 和$符号 。
比如,Person$Heart.class
25.1 重名
外部类成员变量内部类成员变量内部类局部变量重名
25.2 局部内部类
25.2.1 定义
如果一个类是定义在一个方法内部的,那么这就是一个局部内部类。 “局部”:只有当前所属的方法才能使用它,出了这个方法外面就不能用了。
25.2.2 定义格式
只要之后在psvm中调用Outer.methodOuter()方法就行
25.2.3 局部内部类里的final
25.2.4 注意事项
25.3 匿名内部类
25.3.1 定义
是内部类的简化写法。它的本质是一 带具体实现的 父类或者父接口的 匿名的 子类对象。
25.3.2 定义格式
接口名称 对象名 = new 接口名称(){
? //覆盖重写所有抽象方法
};
对格式"new 接口名称(){…}"进行解析:
1、new代表创建对象的动作
2、接口名称才是匿名内部类需要实现哪个接口
3、{……}这才是你们内部类的内容
25.3.3 注意
1.匿名内部类,在【创建对象】的时候,只能使用唯一一次。 如果希望多次创建对象,而且类的内容一样的话,那么就必须使用单独定义的实现类了。
2.匿名对象,在【调用方法】的时候,只能调用唯——次。 如果希望同一个对象,调用多次方法,那么必须给对象起个名字。
3.匿名内部类是省略了【实现类/子类名称】,但是匿名对象是省略了【对象名称】
26 引用类型用法总结
基本类型可以作为成员变量、作为方法的参数、作为方法的返回值,那么当然引用类 型也是可以的。
26.1 class作为成员变量
类作为成员变量时,对它进行赋值的操作,实际上,是赋给它该类的一个对象。
class Weapon {
String name;
int hurt;
}
class Role {
int id;
int blood;
String name;
Weapon wp;
public Weapon getWp() {
return wp;
}
public void setWeapon(Weapon wp) {
this.wp = wp;
}
public void attack(){
System.out.println("使用"+ wp.getName() +", 造成"+wp.getHurt()+"点伤害");
}
}
public class Test {
public static void main(String[] args) {
Weapon wp = new Weapon("屠龙刀" , 999999);
Role r = new Role();
r.setWeapon(wp);
r.attack();
}
}
输出结果:
使用屠龙刀,造成999999点伤害
26.2 interface作为成员变量
接口是对方法的封装,对应游戏当中,可以看作是扩展游戏角色的技能。所以,如果想扩展更强大技能,我们在 Role 中,可以增加接口作为成员变量,来设置不同的技能。
public interface FaShuSkill {
public abstract void faShuAttack();
}
public class Role {
FaShuSkill fs;
public void setFaShuSkill(FaShuSkill fs) {
this.fs = fs;
}
public void faShuSkillAttack(){
System.out.print("发动法术攻击:");
fs.faShuAttack();
System.out.println("攻击完毕");
}
}
public class Test {
public static void main(String[] args) {
Role role = new Role();
role.setFaShuSkill(new FaShuSkill() {
@Override
public void faShuAttack() {
System.out.println("纵横天下");
}
});
role.faShuSkillAttack();
role.setFaShuSkill(new FaShuSkill() {
@Override
public void faShuAttack() {
System.out.println("逆转乾坤");
}
});
role.faShuSkillAttack();
}
}
输出结果:
发动法术攻击:纵横天下
攻击完毕
发动法术攻击:逆转乾坤
攻击完毕
我们使用一个接口,作为成员变量,以便随时更换技能,这样的设计更为灵活,增强了程序的扩展性。 接口作为成员变量时,对它进行赋值的操作,实际上,是赋给它该接口的一个子类对象。
26.3 interface作为方法参数和返回值类型
当接口作为方法的参数时,需要传递什么呢?当接口作为方法的返回值类型时,需要返回什么呢?对,其实都是它的 子类对象。 ArrayList 类我们并不陌生,查看API我们发现,实际上,它是 java.util.List 接口的实现类。所 以,当我们看见 List 接口作为参数或者返回值类型时,当然可以将 ArrayList 的对象进行传递或返回。
27 拼手气红包案例(?)
接口
public interface OpenMode {
public abstract ArrayList<Integer> divide(int totalMoney, int count);
}
普通红包
public class RedPacketTest {
public static void main(String[] args) {
RedPacket rp = new RedPacket("大红包");
rp.setOwnerName("我是群大大");
rp.setOpenMode(new Common());
}
}
public class Common implements OpenMode {
@Override
public ArrayList<Integer> divide(int totalMoney, int count) {
ArrayList<Integer> list = new ArrayList<>();
int time = count ‐ 1;
int money = totalMoney / count;
for (int i = 0; i < time; i++) {
list.add(money);
totalMoney ‐= money;
}
list.add(totalMoney);
System.out.println("普通红包金额:" + list);
return list;
}
}
手气红包
public class RedPacketTest {
public static void main(String[] args) {
RedPacket rp = new RedPacket("大红包");
rp.setOwnerName("我是群大大");
rp.setOpenMode(new Lucky());
}
}
public class Lucky implements OpenMode {
@Override
public ArrayList<Integer> divide(int totalMoney, int count) {
ArrayList<Integer> list = new ArrayList<>();
int time = count ‐ 1;
Random random = new Random();
for (int i = 0; i < time; i++) {
int money = random.nextInt(totalMoney / count * 2) + 1;
list.add(money);
totalMoney ‐= money;
count‐‐;
}
list.add(totalMoney);
return list;
}
}
|