一、计算机基础知识
(一)快捷键
- Ctrl+C:复制
- Ctrl+V:粘贴
- Ctrl+A:全选
- Ctrl+X:剪切
- Ctrl+Z:撤销
- Ctrl+S:保存
- Alt+F4:关闭窗口
- Shift+Dlete:永久删除
- Win+D:回到桌面
- Win+E:打开我的电脑
- Win+R:打开运行
- Ctrl+Shift+Esc:打开任务管理器
- Win+Tab:切换应用
- Win+R 输入cmd:打开cmd
(二)常用Dos命令
- 盘符切换
- 查看当前目录下所有文件 dir
- 切换目录 cd change directory->cd /d directory
- 返回上一级 cd..
- 清理屏幕 cls(clear screen)
- 退出终端 exit
- 查看版本 java -version
- ping 命令
ping www.baidu.com - 文件操作
md(创建目录)
rd(移除目录)
cd>(创建文件)
del(删除文件)
(三)Markdown语法详解
视频教程
Java学习路线(java黑马学习路线)
一、Java基础(其他人的笔记)
(一)jdk安装与环境配置
jdk安装和配置环境教程视频
(二)开发工具(IntelliJ IDEA)安装
idea破解版安装教程视频
具体步骤
(三)idea开发java程序步骤
- project(工程)->module(模块)->package(包)->class(类)
- New project/module/package/class
- 编译后的class文件在工程路径下的一个out文件夹里
(四)idea快捷键
(五)idea其他操作
视频教程
//lombok技术可以实现为类自动添加getter setter方法、无参构造器、toString方法等。
@Data //@Date注解可以自动生成getter setter方法、无参构造器、toString方法等
@NoArgsConstructor //自动生成无参构造器
@AllArgsConstructor //自动生成有参构造器
(六)Java基础语法
Ⅰ.注释
- 单行注释://
- 多行注释:/**/
- 文档注释:/** */
Ⅱ.数据类型
- 基本数据类型:4大类8种
- 引用数据类型:String
- 随便写的整数字面量默认是int类型,加上L/l就是long类型的数据了
- 随便写的小数字面量默认是double类型,加上F/f就是float类型的数据了
Ⅲ.标识符
- 标识符就是名字
- 标识符规则:由数字,字母,下划线,美元符等组成,且不能数字开头,不能用关键字,不能用特殊符号(&,%···)
Ⅳ.方法的一些注意事项
- 方法可以重载
- 一个类中,出现多个方法的名称相同,但它们的形参列表是不同的,那么这些方法就称为方法重载。(通过方法名称标记同一功能,通过参数进行差异化。)
- 无返回值的方法中可以直接通过单独的return;立即结束当前方法的执行。
Ⅴ.自动-强制类型转换
- 为什么要进行类型转换
- 存在不同类型的变量赋值给其他类型的变量
- 什么是自动类型转换
- 类型范围小弟变量,可以直接赋值给类型范围大的变量
- 什么是强制类型转换
- 默认情况下,大范围类型的变量直接赋值给小范围类型的变量会报错
- 可以强行将类型范围大的变量、数据赋值给类型范围小的变量
数据类型 变量=(数据类型)变量、数据
- 强制类型转换有哪些需要注意的
- 大转小可能出些数据丢失
- 小数强制转换成整数是直接截断小数保留整数
Ⅵ.表达式的自动类型提升
- 小范围的类型会自动转换成大范围的类型运算
- 最终类型由表达式中的最高类型决定
- byte short char式直接转换成int类型参与运算的
Ⅶ.输入-输出
- 输入:System.out.println(“”);
- 输出
(1) 导包(告诉程序去JDK的哪个包中找扫描器技术):import java.util.Scanner;
(2) 得到键盘扫描器对象(东西):Scanner sc=new Scanner(System.in);
(3) 等待接收用户输入数据:String name=sc.next();/int age=sc.nexitInt();
Ⅷ.逻辑运算符
- &:有一个为false、结果是false
- &&:有一个为false、结果是false,但前一个为false,后一个条件就不执行了
- |:有一个为true、结果是true
- ||:有一个为true、结果是true,但前一个为true,后一个条件就不执行了
- ^:相同是false、不同是true
Ⅸ.switch分支-穿透性
- switch分支结构
点击查看代码
switch(表达式){
case 值1:
执行代码...;
break;
case 值2:
执行代码...;
break;
...
case 值n-1:
执行代码...;
braek;
default:
执行代码n;
}
- 注意事项
- 表达式类型只能是byte、short、int、char,JDK5开始1支持枚举,JDK7开始支持String、不支持double、float、long。
- case给出的值不允许重复,且只能是字面量,不能是变量。
- 正常使用switch的时候,不要忘记写break,否则会出现穿透现象。
- 存在多个case分支的代码是一样时,可以把代码写到一个case块,其他case块通过穿透性能,穿透到该case块即可,这样可以简化代码。
Ⅹ.三种循环的使用(for、while、do-while)
for循环中,控制循环的变量只在循环中使用。while循环中,控制循环的变量在循环后还可以继续使用。
ⅩⅠ.跳转关键字
- break:跳出并结束当前所在循环的执行。
- continue:用于跳出当前循环的当次执行直接进入循环的下一次执行。
ⅩⅡ.生成随机数
- Math.random()反回[0,1)的随机数字
- import java.util.Random;
Random r=new Random();//得到一个随机数对象
int luckNumber=r.nextInt(100)+1;//[0,99]+1=>[1,100]
ⅩⅢ.开平方
Math.sqrt(number)
ⅩⅣ.数组
- 静态初始化数组,定义已经确定了数据
数据类型[] 数组名={元素1,元素2,元素3,…};
如:int[] arr={12,24,36}; - 完整格式
数据类型[] 数组名=new 数据类型[]{元素1,元素2,元素3,…};
如:int[] arr=new int[]{12,24,36}; - “数据类型[] 数组名”也可写成”数据类型 数字名[]”的形式,定义数组的三种方法
1.String[] names={“”,””};
2.String names[]={“”,””};
3.String[] names=new String[]{“”,””}; - names.length: 获取数组的长度(元素个数)
- 动态初始化数组定义数组时先不存入具体的元素,只确定数组存储的数据类型和数组的长度
数据类型[] 数组名=new 数据类型[长度];
int[] arr=new int[3]; - 动态初始化数组元素默认值规则:
(七)面向对象编程
面向对象三大特征:封装、继承、多态。
- 对象
特殊的数据结构,一个实体,有属性和行为。也可以理解为一张表。 - 类(对象类)
特殊的数据结构,有属性和行为。类只在计算机中加载一次。 - 内存分配
java在内存的JVM虚拟机上运行,JVM虚拟机又分为堆内存、栈内存和方法区一同执行程序。
变量存在栈里,变量指向对象,对象存在堆里,对象指向类,类存在方法区,将方法区中的方法调到栈中执行
万物皆对象,一个数据由一个对应的对象处理,我们设计对象时就是在设计类(对象的模板)。
Ⅰ.类的基本语法
- 构造器
(1)构造器(分为无参构造器和有参构造器):类中定义的方法,用来初始化对象,在类中定义的方法,称为方法,在类中定义的变量,称为属性。 名字与类名一致,无返回值,无返回值类型,无访问修饰符。
(2)特点:创建对象时,对象会自动调用构造器,如果没有定义构造器,JVM会自动生成一个无参构造器。
(3)应用场景:创建对象时,调用构造器,立即初始化对象成员变量的值。
(4)注意:类默认有一个无参构造器(没有显示而已),若你自己定义了有参构造器,那么类默认的无参数构造器就没有了,此时如果还想用无参数构造器,就必须自己手写一个无参构造器出来。 - this关键字
(1)this 关键字:是一个变量,可以用在方法中,用来拿到当前对象;哪个对象调用方法,this就指向哪个对象,也就是拿到哪个对象。
(2)应用场景:用来解决对象的成员变量与方法内部变量的名称一样时,导致访问冲突问题的。
点击查看代码
public void print(String name){//this关键字解决变量冲突问题
System.out.println(name+this.name);//this.name拿到的是对象变量(成员变量)name,而不是局部变量name
}
- 封装
(1)就是用类设计对象处理某一个事物的数据时,应该把要处理的数据,以及处理这些数据的方法,设计到一个对象中去。
(2)封装的设计要求:合理隐藏、合理暴露。
(3)(合理隐藏)使用private(私有、隐藏)关键字进行修饰,防止用户在其他类中随意对本类内的变量修改数据,只允许在本类中直接被访问。
(3)(合理暴露)使用get和set方法,用public(公开)进行修饰,让用户在类外直接调用,修改数据。 - 实体类(JavaBean)
(1)实体类:仅仅只是一个用来保存数据的java类,可以用它创建对象,保存某个事物的数据。
(2)特点:成员变量必须私有,提供get和set方法;必须有无参构造器。
(3)应用场景:实体类的对象只负责数据的封装,不涉及任何业务逻辑。而数据的业务处理交给其他类的对象来完成,以实现数据和业务处理相分离(解耦)。 - static修饰成员变量
(1)static关键字:叫静态,可以修饰成员变量、成员方法。
(2)静态变量(类变量):有static修饰,属于类,在计算机里只有一份,被类的全部对象共享,所有对象都可以访问。
类名.静态变量(推荐)
对象名.静态变量(不推荐)
(3)实例变量(对象的变量):没有static修饰,属于每个对象,每个对象都有自己的变量,对象可以访问。
对象.实例变量
(4)应用场景:如果某一个数据只需要一份,并且希望能够被共享(访问、修改),则该数据被定义成静态变量。 (如用户类,记录了创建了多少个用户对象)
(5)访问自己类中的类变量,可以省略类名不写。
注意:在某个类中访问其他类里的类变量,必须带类名。 - static修饰方法
(1)(有static修饰)静态方法:有static修饰的成员方法,属于类,最好用类名调用,少用对象名调用。
(2)(无static修饰)实例方法:无static修饰的成员方法,属于对象,用对象名调用,不能用类名调用。
规范:如果一个方法只是为了做一个功能且不需要直接访问对象的数据,这个方法直接定义为静态方法。
如果这个方法是关于对象的行为,需要访问对象的数据,这个方法必须定义为实例方法。
(3)比如在main方法中,我们直接调用其他方法,是用类名调用,只不过类名在同一类中可以忽略不写。(main方法是静态方法) - 工具类与静态方法
(1)工具类:封装了多个静态方法,每个方法用来完成一个功能,给开发人员直接使用。
(2)区别:实例方法需要创建对象来调用,此时对象占用内存,而静态方法不需要,可以减少内存消耗;静态方法可以用类名调用,调用方便,能节省内存。
点击查看代码
public class StaticAbout {//工具类
//工具类没有创建对象的必要性,建议将工具类的构造器私有化。
private StaticAbout() {
}
public static String getCode(int n) {//静态方法与工具类
String code = "";
for (int i = 0; i < n; i++) {
int type = (int) (Math.random() * 3);//0-9 1-26 2-26
switch (type) {
case 0:
code += (int) (Math.random() * 10);
break;
case 1:
code += (char) (Math.random() * 26 + 'a');//得到小写字母的区间
break;
case 2:
code += (char) (Math.random() * 26 + 'A');
}
}
return code;
}
}
- 静态方法与实例方法访问注意事项
(1)静态方法中可直接访问静态成员,不可直接访问实例成员。
(2)实例方法中即可直接访问静态成员,也可直接访问实例成员。
(3)实例方法中可以出现this关键字,静态方法中不可出现this关键字。
点击查看代码
public class Attention{
public static int count=100;//静态变量
public static void print(){//静态方法
System.out.println("Hello World!");
}
public String name;//实例变量,属于对象
public void prints(){//实例方法,属于对象
}
public static void main(String[] args) {
}
//(1)、静态方法中可直接访问静态成员,不可直接访问实例成员。
public static void printTest1(){
System.out.println(count);
print();
//System.out.println(name);//报错
//prints();//报错
//System.out.println(this);//报错,this代表的只能是对象
System.out.println(Attention.count);
}
//(2)、实例方法中即可直接访问静态成员,也可直接访问实例成员。
public void printTest2(){
System.out.println(count);
print();
System.out.println(name);
prints();
System.out.println(this);//实例方法中,this代表的是当前对象
}
}
Ⅱ.面向对象高级
一)继承
- 继承
(1)继承关键字:extends,可以让一个类与另一个类建立起父子关系
public calss B extends A{}//其中A是父类,B是子类
(2)只能继承父类的非私有成员(成员变量、成员方法)
(3)继承后的创建:子类的对象是由子类、父类共同完成的。
(4)继承的好处:代码重用,减少代码量,提高效率。 - 权限修饰符
用来限制类中的成员(成员变量、成员方法、构造器)能够被访问的范围。
修饰符 | 本类里 | 同一个包中的其他类 | 子孙类(包括不同包的) | 任意类 |
---|---|---|---|---|
private | √ | |||
缺省 | √ | √ | ||
protected | √ | √ | √ | |
public | √ | √ | √ | √ |
点击查看代码
public class Father {
private void privateMethod() {//二、2、权限修饰符之私有方法
System.out.println("private method");
}
void defaultMethod() {//二、2、权限修饰符之缺省方法
System.out.println("default method");
}
protected void protectedMethod() {//二、2、权限修饰符之受保护方法
System.out.println("protected method");
}
public void publicMethod() {//二、2、权限修饰符之公共方法
System.out.println("public method");
}
public static void main(String[] args) {//本类中可以调用的所有方法
Father father = new Father();
father.privateMethod();
father.defaultMethod();
father.protectedMethod();
father.publicMethod();//所有类都可以调用public方法
}
}
//以下为同一包的子类
class SonA extends Father {
public void test() {
//privateMethod();//子类中不可以访问父类的私有方法
defaultMethod();//子类中可以访问父类的缺省方法
protectedMethod();//子类中可以访问父类的受保护方法
publicMethod();//子类中可以访问父类的公共方法
}
}
//以下为不同包的子类
class SonC extends Father {
public void test() {
//privateMethod();//子类中不可以访问父类的私有方法
//defaultMethod();//不同包的子类中可以访问父类的缺省方法
protectedMethod();//不同包的子类中可以访问父类的受保护方法
publicMethod();//不同包的子类中可以访问父类的公共方法
}
}
//以下为不同包的非子类
class main {
public static void main(String[] args) {
Father father = new Father();
//father.privateMethod();
//father.defaultMethod();
//father.protectedMethod();
father.publicMethod();//其他包中,只能访问public方法
}
}
- 继承的特点
单继承 | 一个类只能继承一个直接父类 |
---|---|
多层继承 | 不支持多继承,但支持多层继承(多继承的话若两个父类出现相同方法,无法判断调用哪个) |
祖宗类 | Java中的所有类都是Object类的子类(一个类要么直接继承Object,要么默认继承Object,要么间接继承) |
就近原则 | 优先访问自己类中,自己类中的没有才访问父类,父类也没有就报错(访问父类的成员要加super) |
点击查看代码
public class TestFeature{//测试类
//二、3、继承的特点
public static void main(String[] args) {
zilei zi=new zilei();
zi.test();
}
}
class fulei{
String name="FUlei";
public void run(){
System.out.println("fuleiRun");
}
}
class zilei extends fulei{
String name="ZiLei";
public void run(){
System.out.println("zileiRun");
}
public void test(){
String name="ZiLeiTEST";
System.out.println(name);//test的name
System.out.println(this.name);//zilei的name
System.out.println(super.name);//fulei的name
run();//zilei的run优先级更高
this.run();//zilei的run
super.run();//fulei的run
}
}
- 方法重写(声明不变,重新实现)
(1)重写小技巧:使用Override注解(@Override),它可以指定java编辑器,检查我们方法重写的格式是否正确,代码的可读性也会更好。
(2)方法重写:子类写了一个方法名称,形参列表与父类某个方法一样的方法去覆盖父类的该方法。
(3)子类重写父类方法时,访问权限必须大于或等于父类的该方法的权限(public>protected>缺省)
(4)重写的方法返回值类型,必须与被重写方法的返回值类型一样,或者范围更小。
(5)私有方法(不能被继承所以不能被重写)和静态方法(自己调用)不能被重写,否则报错。
点击查看代码
public class TestOverride {
public static void main(String[] args) {//二、4、方法重写
animal a=new cat();
//用父类申明对象,利用多态性和向上转型的概念,以实现更加灵活和可扩展的程序设计,降低代码的耦合性
a.eat();
cat b=new cat();
b.eat();
}
}
class animal{
public void eat(){System.out.println("animal eat");}
}
class cat extends animal{
@Override//方法重写的校验注解(标志),要求重写的方法与父类方法签名一致,否则编译报错,可读性好
public void eat(){System.out.println("cat eat!!!");}
}
- 重写toString方法
点击查看代码
public class TestOverride {
public static void main(String[] args) {
animal a=new animal();
System.out.println(a);
//若没重写toString方法,则返回:com.rasion.extendANDpolymorphism.extend.cat@4e50df2e
System.out.println(a.toString());
//我们直接输出对象,会默认调用Object的toString方法,返回对象的地址信息
//故我们可以重写toString方法,返回我们想要的信息
}
}
class animal{
private String name;
@Override
public String toString() {//重写toString方法,返回我们想要的信息
return "animal{" +
"name='" + name + '\'' +
'}';
}
}
- 子类构造器
(1)子类构造器,必须先调用父类的构造器,再执行自己的构造器。(可以用super(···)指定调用父类的有参构造器)
(2)默认情况下,子类构造器第一行代码都是super()(写不写都有),他会调用父类的无参构造器,若父类没有无参构造器,则报错。
(3)如果父类没有无参构造器,则我们必须在子类构造器的第一行手写super(···),指定去调用父类的有参数构造器。
(4)应用场景:有一些参数是处在父类中,子类没有,但子类需要用到,这时,子类构造器中,可以先调用父类的有参构造器,为对象中包含父类这部分的成员变量进行赋值,再调用子类的构造器。 - 构造器用this(…)调用兄弟构造器(实现填写默认信息)
(1)一般调用兄弟构造器(在构造器中调用本类的其他构造器),可以实现代码复用。
(2)注意:super(..) this(…)必须写在构造器第一行,并且不能同时出现。(兄弟构造器只需要一个调用父类构造器即可)
点击查看代码
public class User{
private String name;
private int age;
private String school;
//...此处省略get、set方法toString方法
public User(String name, int age) {
this(name, age, "黑马");//调用本类其他构造器,以实现填写默认信息
}
public User(String name, int age, String school) {
this.name = name;
this.age = age;
this.school=school;
}
}
二)多态
- 多态
(1)多态是在继承/实现的情况下的一种现象,表现为:对象多态、行为多态(对象的多样性,行为的多样性,但是没有成员变量的多态性)
(2)多态前提:有继承/实现关系;存在父类引用子类对象;存在方法重写。
(3)注意:多态是对象、行为的多态,java中的属性(成员变量)不谈多态。
点击查看代码
people p1=new student();//对象多态
p1.run();//行为多态
people p2=new teacher();//对象多态
p2.run();//方法:编译看左边,运行看右边
System.out.println(p2.name);//成员变量:编译看左边,运行也看左边
- 多态的好处、问题
(1)在多态形式下,右边的对象是解耦合的,更便于扩展和维护。
(2)定义方法时,使用父类类型的形参,可以接收一切子类对象,扩展性更强、更便利。
(3)问题:多态下不能使用子类的独有功能。
点击查看代码
public class TestPolymorphism {
public static void main(String[] args) {
people p1=new student();//多态调用不了子类的独有功能
people p2=new teacher();
show(p1);
show(p2);
System.out.println(p1.name);//成员变量:编译看左边,运行也看左边
}
public static void show(people p) {
//父类类型作为参数,可以接收一切子类变量
System.out.println("=====+++=====");
p.run();//调用方法:编译看左边,运行看右边
}
}
- 多态下的类型转换(instanceof判断)
(1)自动类型转换:父类 变量名=new 子类();例如:People p=new Teacher();
强制类型转换:子类 变量名=(子类) 父类变量;例如:Teacher t=(Teacher)p;
(2)可以把对象转换成其真正的类型,从而解决了多态下不能调用子类独有方法的问题。
(3)存在继承/实现时,就可以进行强制类型转换,编译阶段不会报错。
但在运行时,如果发现对象的真实类型与强制转换后的类型不同,就会报类型异常(ClassCastException)的错误。
(4)在强转前可以用instanceof关键字判断对象的真实类型,再进行强转:对象 instanceof 类型。
点击查看代码
public class TestPolymorphism {
public static void main(String[] args) {
people p1=new student();
people p2=new teacher();
student s=(student)p1;//强制类型转换
//teacher t=(teacher)p1;//转换错误,因为p1是student类型
//编译阶段有类型强转不会报错,运行阶段会报错
show(p1);
show(p2);
}
public static void show(people p) {
if(p instanceof teacher) {//判断类型,一般会在方法中写,来判断p是否为teacher类型
teacher t=(teacher)p;
...//调用teacher的独有功能
}else if(p instanceof student) {
student s=(student)p;
...//调用student的独有功能
}
}
}
三)final(最终)
- final关键字用来修饰类、方法、变量。
(1)修饰类:代表该类不能被继承,为最终类。(一般是用在工具类中)
(2)修饰方法:代表该方法不能被重写,为最终方法。
(3)修饰变量(局部变量、成员变量(静态、实例)):代表该变量有且仅能被赋值一次。(一般是修饰静态变量)
(4)final修饰基本类型(int,double,boolean,char…)的变量,变量存储的数据不能被改变。
(5)final修饰引用类型(String,Array…)的变量,变量存储的地址不能被改变,但地址所指向的对象的内容是可以被改变的。
2、常量
(1)使用了static final修饰成员变量为常量。
(2)作用:通常使用常量记录系统配置信息;常量都统一到常量包内(Constant),方便修改。
(3)注意!常量名的命名规范:建议使用大写英文单词,多个单词使用下划线连接起来。
(4)程序编译后,常量会被“宏替换”:出现常量的地方全部会被替换成其记住的字面量,减少内存消耗,这样可以保证使用常量和直接使用字面量的性能是一样的。
点击查看代码
public class Constant {//常量包
public static final String NAME = "rasion";
}
四)单例类(设计模式)
- 什么是设计模式:程序中一个问题n种解法中的最优解(设计模式主要学:解决什么问题、怎么写)(设计模式有20多种,对应20多种软件开发中会遇到的问题)
- 单例设计模式
(1)作用:确保某个类只有只能创建一个对象。
(2)把类的构造器私有。(确保单例类对外不能创建太多对象,单例才有可能性)
(3)定义一个类变量存储本类的一个唯一对象。
(4)定义一个类方法,返回这个类的唯一对象。 - 单例应用场景:任务管理器对象、获取运行时对象(有且仅需要一个对象)
- 饿汉式单例类:在获取类的对象时,对象已经创建好了。
点击查看代码
public class A {//饿汉式单例类:拿对象的时候对象早已生成,无论是用不用,都会创建。
private A(){}//1、私有化构造器
private static A a=new A();//2、实例化私有静态变量
//当类被加载时,静态变量a会被初始化,此时类的私有构造函数会被调用。这时候,单例类的唯一实例就被创建出来了。
public static A getObject(){
return a;
}//3、定义一个类方法返回对象
}
- 懒汉式单例类:用对象时,才开始创建对象(延迟加载对象)。
(1)把类的构造器私有。
(3)定义一个静态(类)变量用于存储对象。
(4)提供一个静态(类)方法,保证返回的是同一个对象。
点击查看代码
public class B {//懒汉式单例类:拿对象的时候才创建,真正需要对象时才开始创建。
private B(){}//1、私有化构造器
private static B b;//2、定义一个类变量用于存储对象
public static B getInstance(){//提供一个类方法返回类的唯一对象
if(b==null){
//第一次拿对象时,会创建对象,给静态变量b记住。
b=new B();
}
return b;
}
}
五)枚举类(一种特殊类)
- 枚举类的写法:
修饰符 enum 枚举类名{
名称1,名称2,名称3;
其他成员...
}
- 特点:
(1)枚举类中的第一行,只能写枚举类的对象名称,且要用逗号隔开。
(2)这些名称,本质是常量,每个常量都记住了枚举类的一个对象。
(3)枚举都是最终类,不可以被继承,枚举类都是继承java.lang.Enum类的。
点击查看代码
public enum A {//枚举类
X,Y,Z;//枚举类第一行只能罗列一些名称,这些名称都为常量,并且每个常量会记住枚举类的一个对象
}
Compiled from "A.java"//对A.java的反编译
public final class A extends java.lang.Enum<A>{//枚举类继承了Enum
public static final A X=new A();//枚举类第一行只能罗列一些名称,这些名称都为常量,并且每个常量会记住枚举类的一个对象
public static final A Y=new A();//如果只有一个Y的话,可以被视为单例类。
public static final A Z=new A();
//枚举类的构造器都是私有的(写不写都只能是私有的),因此,枚举类对外不能创建对象。
public static A[] values();//返回枚举类的所有实例
public static A valueOf(java.lang.String var0);//返回指定名称的枚举实例
}
- 枚举类的常用应用场景:适合做信息分类和标志
(1)枚举类常用于定义常量,枚举类中的常量只能是枚举类的实例,不能被修改。
(2)虽说用也可以用常量类做信息分类和标志,但是参数值不受约束(就是传入的参数不是限定内的那四个都能行的通,写别的不报错),但是枚举类的话写限定外的就会报错。
六)抽象类
- 在java中有一个关键字叫:abstract(抽象),可以用它修饰类、成员方法。
- abstract修饰类,这个类就是抽象类。
- abstract修饰方法,这个方法就是抽象方法。
修饰符 abstract class 类名{
修饰符 abstract 返回值类型 方法名称(形参列表);
}
抽象方法只有方法签名,不能写方法体。 - 抽象类的注意事项、特点
(1)抽象类不一定要有抽象方法,有抽象方法的类必须是抽象类。
(2)类有的成员:成员变量、方法、构造器,抽象类都可以有。
(3)抽象类最主要的特点:抽象类不能创建对象,仅作为一种特殊的父类,让子类继承并实现。
(4)一个类继承抽象类,必须重写完抽象类的全部抽象方法,否则这个类也必须定义为抽象类。
点击查看代码
public abstract class A {//抽象的本质是不能有对象,抽象类的基本作用就是被继承
private String name;//抽象类有成员变量
public A(){System.out.println("抽象类A的构造方法");}//抽象类有构造方法
public void show(){System.out.println("抽象类A的show方法");}//抽象类的方法可以有方法体
//抽象方法,抽象类中可以有没有抽象方法,抽象方法没有方法体,只有方法声明,子类必须重写抽象方法
public abstract void show();//抽象类的抽象方法不能写方法体
}
- 抽象类的应用场景和好处:父类知道每个子类都要做某个行为,但每个子类要做的情况不一样,父类就定义成抽象方法,交给子类去重写实现,我们抽出这样的抽象类,就是为了更好的支持多态。(抽象类简化了需要重写的父类方法的代码,更加便于调用子类时多态的实现,更具解耦性。)
- 模板方法设计模式:
(1)提供了方法作为完成某类操作的模板,模板方法封装了每个实现步骤,允许子类实现特定步骤的实现。
(2)解决方法中存在重复代码的问题。
(3)定义一个抽象类,在里面定义2个方法,一个是模板方法:放相同的代码,一个是抽象方法:具体实现交给子类完成。
(4)建议使用final关键字修饰模板方法。(模板方法不能被子类重写,一旦子类重写了模板方法,模板方法就失效了)
点击查看代码
public abstract class fu {//父类抽象类
public final void show(){//模板方法不能被重写
System.out.println("模板方法");//子类共同的部分
show1();//子类不同的部分
}
public abstract void show1();//抽象方法,子类一定要重写,不然就报错,这样做是最佳实现
}
public class A extends fu {//子类
@Override
public void show1(){System.out.println("A show1方法");}
}
public class B extends fu {//子类
@Override
public void show1(){System.out.println("B show1方法");}
}
七)接口(相当于干爹)
- Java提供了一个关键字interface定义出接口。
public interface 接口名{
//成员变量(常量)
//成员方法(抽象方法)
}
(1)传统接口:内部只能写常量和抽象方法(jdk8以前)。
(2)常量:接口中的常量默认是public static final的,所以可以省略。
(3)抽象方法:接口中的抽象方法默认是public abstract的,所以可以省略。 - 注意:接口不能创建对象。
- 接口是用来被类实现(implements)的,实现接口的类称为实现类,一个类可以同时实现多个接口。
修饰符 class 实现类类名 implements 接口1,接口2,接口3,···{
//实现类实现多个接口,必须重写完全部接口的全部抽象方法,否则实现类需要定义成抽象类。
}
点击查看代码
public interface A {//接口不能创建对象,只能被实现
//JDK-8之前,接口只能定义常量和抽象方法,不能定义具体方法。
//1、常量:接口中的常量默认是public static final的,所以可以省略。
String NAME="rasion";
//2、抽象方法:接口中的抽象方法默认是public abstract的,所以可以省略。
// public abstract void show();
void show();
}
public class C implements A,B {//实现接口的类,可以实现多个接口
@Override
public void show() {
System.out.println("C实现A\B接口的show方法");
}
}
- 接口的好处:
(1)弥补了类单继承的不足,可以实现多接口,使类的角色更多,功能更加强大(接口可以是一种属性)。
(2)让程序可以面向接口编程,这样程序员就可以灵活方便的切换各种业务实现(更利于程序的解耦合)。
点击查看代码
public class test {
public static void main(){
// Driver d=new Teacher();//做接口解耦合,可以不改变自己本来的代码
Driver d=new Student();
Cook c=new Student();
}
}
public interface Driver {}
public interface Cook {}
class people{}//抽象类
class Teacher extends people implements Driver,Cook{}//实现多个接口,用逗号隔开
class Student extends people implements Driver,Cook{}
- JDK8开始,接口新增了三种形式的方法:
(1)默认方法:使用default修饰,使用实现类的对象调用。
(2)静态方法:static修饰,必须当前接口名来调用。
(3)私有方法:private修饰,jdk9开始才有的,只能在接口内部被调用。
(4)他们都会默认被public修饰。
(5)新增的方法增强接口能力,更便于项目扩展与维护(若新增方法,可以直接写在接口中,不用修改实现类,更方便扩展)
点击查看代码
//jdk-8之后的三种方法
//a、默认方法,一定要加default修饰符,默认会用public修饰,用接口的实现类对象调用
default void defaultMethod(){
System.out.println("defaultMethod");
privateMethod();
}
//b、静态方法,一定要加static修饰符,默认会用public修饰,只能用当前接口名来调用
static void staticMethod(){//静态方法
System.out.println("staticMethod");
}
//c、私有方法,一定要加private修饰符,默认会用private修饰,用接口中的其他实例方法调用
private void privateMethod(){//私有方法
System.out.println("privateMethod");
}
- 注意事项:
(1)接口与接口可以多继承,一个接口可以同时继承多个接口,但接口不能继承类。
类与类:单继承,一个类只能继承一个直接父类。
类与接口:多实现,一个类可以同时实现多个接口
(2)一个接口继承多个接口,若多个接口中出现方法签名冲突,此时不支持多继承,也不支持多实现(即两个接口都有同一个方法名,但是方法签名不同,即方法类型不同,则报错)。
(3)一个类继承了父类,同时又实现接口,若父类与接口中有同名的方法,则会优先实现父类的方法。(若想调用接口的方法只能新建中专方法,接口名.super.方法名)
(4)一个类实现多个接口,如果多个接口中存在同名的默认方法,要想不冲突,这个类重写该方法即可。 - 抽象类与接口区别:
相同点:
(1)都是抽象形式,都可以有抽象方法,都不能创建对。
(2)都是派生子类形式:抽象类是被子类继承使用,接口是被实现类实现。
(3)一个类继承抽象类,或者实现接口,都必须重写他们的抽象方法,否则自己要成为抽象类或者报错!
(4)都能支持多态,都能实现解耦合。
不同点:
(1)抽象类中可以定义类的全部普通成员,接口只能定义常量、抽象方法,(JDK8新增的三种方式)。
(2)抽象类只能被类单继承,但是接口可以被类多实现。
(3)一个类继承抽象类就不能再继承其他类,一个类实现了接口(还可以继承其他类或者实现其他接口)。
(4)抽象类体现模板思想,更利于做父类的,实现代码的复用性;接口更适合做功能的解耦合,解耦合更加灵活。(最佳实现)
八)代码块
- 类的五大成分:成员变量、构造器、方法、代码块、内部类。
- 静态代码块:
(1)格式:static{ }
(2)特点:类加载时自动执行,由于类只会加载一次,所以静态代码块只执行一次,优先考虑于构造器执行。
(3)作用:完成类的初始化(如:对静态变量的初始化赋值)。
(4)import java.util.Arrays:
System.out.println(Arrays.toString(cards));
//返回数组的内容观察 - 实例代码块
(1)格式:{ }
(2)特点:每次创建对象时,执行实例代码块,并在构造器前执行。
(2)作用:和构造器一样,都是用来完成对象的初始化的(如:对实例变量进行初始化赋值)。
点击查看代码
public class codeBlock {
public static String NAME;
public static String[] CARD=new String[54];//初始化数组
static {//静态代码块,有static修饰,属于类,与类一起优先加载,自动执行一次
System.out.println("static block");
NAME="rasion";
CARD[0]="A";//静态数组只需要初始化一次,就可以在静态代码块中初始化
CARD[1]="2";
CARD[2]="3";
}
{//实例代码块,没有static修饰,属于对象,与对象一起加载,对象加载几次,就会执行几次
System.out.println("non-static block");
}
public static void main(String[] args) {
System.out.println("hello main");
System.out.println(NAME);
System.out.println(Arrays.toString(CARD));//打印数组
codeBlock cb=new codeBlock();//创建对象时,会执行实例代码块
new codeBlock();
new codeBlock();
System.out.println(cb);
}
}
九)内部类
- 当一个类被定义在另一个类内部,则该类称为内部类。
- 场景:当一个类的内部,包含了一个完整的事物,且这个事物没有必要单独设计时,就可以把这个事物设计成内部类。
- 成员内部类:
(1)就是类中的一个普通成员,类似前面我们学过的普通的成员变量、成员方法。
(2)创建成员内部类对象格式:
外部类名.内部类名 对象名= new 外部类名().new 内部类名();
Outer.Inter in=new Outer().new Inter();
(3)成员内部类属于外部类对象持有。
(4)成员内部类可以直接访问外部类的静态成员、实例成员。
(5)成员内部类的实例方法中,可以直接拿到当前寄生的外部类对象,格式是:外部类.this.成员名。
点击查看代码
public class main {
public static void main(String[] args) {
// 创建成员内部类对象格式:外部类名.内部类名 对象名= new 外部类名().new 内部类名();
OuterClass.InnerClass innerClass = new OuterClass().new InnerClass();
innerClass.print();//内部类对象调用内部类方法
}
}
public class OuterClass {
//成员内部类:无static修饰,属于外部类的对象持有的
public class InnerClass{//类有的属性,方法内部类都能有
private String num="InnerThis";
public void print(){
System.out.println("===innerMethod===");
outerPrint();
String num="-innerPrint-";
System.out.println(num);
System.out.println(this.num);//内部类对象
System.out.println(OuterClass.this.num);//外部类对象
OuterClass oc=new OuterClass();//创建外部类对象
System.out.println(oc.num);
run();
}
}
//内部类可以访问外部类的静态成员
public static void outerPrint(){//外部类静态方法
System.out.println("OuterClass static print");
}//静态内部类,属于外部类,外部类可以访问
private String num="OuterThis";//外部类成员变量
public void run(){}
}
- 静态内部类:
(1)有static修饰的内部类,属于外部类自己持有。
(2)创建静态内部类对象格式:
外部类名.内部类名 对象名= new 外部类名.内部类名();
Outer.Inner in=new Outer.Inner();
(3)静态内部类可以直接访问外部类的静态成员;静态内部类不可以直接访问外部类的实例成员。
点击查看代码
public class main {
public static void main(String[] args) {
StaticInnerClass.InnerClass innerClass=new StaticInnerClass.InnerClass();//静态内部类对象
innerClass.print();
}
}
public class StaticInnerClass {
public static class InnerClass{
private String NAME="inner rasion";
public void print() {
System.out.println("StaticInnerClass print");
//静态内部类可以直接访问外部类的静态成员
System.out.println("StaticInnerClass NAME:"+StaticInnerClass.NAME);
//静态内部类不可以直接访问外部类的实例成员
// System.out.println("StaticInnerClass age:"+age);
//静态内部类可以间接访问外部类的局部变量
StaticInnerClass staticInnerClass=new StaticInnerClass();
System.out.println("StaticInnerClass age:"+staticInnerClass.age);
}
}
public static String NAME="outer rasion";//外部类的静态成员
public int age=18;//外部类的实例成员,属于外部类对象的
}
- 局部内部类:(了解)
局部内部类:定义在方法中、代码块中、构造器等执行体中(无具体意义,用来引出匿名内部类)。 - 匿名内部类:
(1)一种特殊的局部内部类。
(2)所谓匿名:指的是程序员不需要为这个类声明名字,默认有一个隐藏的名字。
new 类名或接口(参数值...){
类体(一般是方法重写);
};
new Animal(){
@Override
public void cry(){}
};
(3)特点:匿名内部类本质是个子类,并且会立即创建出一个子类对象。
(4)作用:更方便的创建一个子类对象。
(5)匿名内部类在开发中的常见形式:通常作为一个对象参数传输给方法。
(6)匿名内部类在开发中的真实使用场景示例
调用别人提供的方法实现需求时,这个方法正好可以让我们传输一个匿名内部类对象给其使用。(开发中不是主动写匿名内部类,而是调用别人的功能时,需要我们写一个匿名内部类)
点击查看代码
public class AnonymityInnerClass {
public static void main(String[] args) {
//匿名内部类有名字:外部类名$编号.class
//匿名内部类本质是一个子类,同时立即创建一个子类对象
Animal cat=new Animal(){
@Override
public void run() {System.out.println("cat run");}
};//匿名内部类,同cat类,即是一个子类又是一个子类对象
// Animal cat=() -> System.out.println("cat run");//Lambda简化
cat.run();
print(cat);
print(new Animal() {
@Override
public void run() {System.out.println("inner cat run");}
});//同上print(cat);一样功能
}
public static void print(Animal animal){
System.out.println("start==");
animal.run();//匿名类对象回调,由于匿名类相当于子类,所以可以调用子类的方法
}
}
interface Animal{
public abstract void run();
}
//class cat extends Animal{
// @Override
// public void run() {
// System.out.println("cat run");
// }
//}
来源链接:https://www.cnblogs.com/wodexuexibiji/p/19033834
© 版权声明
本站所有资源来自于网络,仅供学习与参考,请勿用于商业用途,否则产生的一切后果将由您(转载者)自己承担!
如有侵犯您的版权,请及时联系3500663466#qq.com(#换@),我们将第一时间删除本站数据。
如有侵犯您的版权,请及时联系3500663466#qq.com(#换@),我们将第一时间删除本站数据。
THE END
暂无评论内容