文章目录
JAVA
核心优势:跨平台
一. Java 语言版本
- Java SE: Java Standard Edition 标准版,核心
- Java EE: Java Enterprise Edition 企业版, 开发企业级应用
- Java ME: 小型版本
- Java Car: 智能卡
二. Java 语言特点
- 跨平台:Java是一个跨平台的语言, 但是JVM不是跨平台的
- 安全性:通过字节码校验器,所以会相对比较安全,不支持指针,杜绝了内存非法访问
- 简洁性:垃圾回收机制
- 面向对象
三. JRE 与 JDK
- JRE: Java Runtime Environment Java运行环境, JRE中包含Java程序运行的核心类库
- JDK: Java Development Kit Java开发工具包,包含了Java的开发工具, 比如 javac
- 使用JDK开发Java程序, 交给JRE去运行(JDK中包含JRE的部分)
四. Java环境的搭建
- 安装路径中不能有中文,空格特殊符号
五. Java程序执行过程
- 书写源码: .java后缀结束
- 使用java命令编译源码: 产生.class文件 (Java文件字节码文件)
- 使用java命令来执行java程序
六. 设置环境变量
-
Path: 可以在任意路径下, 直接执行java的相关命令
(1) 直接把JDK\bin目录加入path中
(2) 更好: 采用引用的方式来设置path -
classpath: 可以在任意路径下直接通过执行java命令来运行java程序
JAVA语法
标识符
表示类名的标识符:每个单词的首字母大写
表示方法和变量的标识符:第一个单词小写, 第二个但是开始首字母大写
标识符必须以字母, 下划线, $开头!
变量(variable)
变量实际上是一个可操作的存储空间, 空间位置是确定的, 内容是不确定的(参考车位), 可通过变量名来访问存储空间内的值, 定义变量时要声明变量的类型
局部变量: 从属于方法,使用前一定要初始化, 在声明位置到方法或语句块执行完毕为止内有效
成员变量(实例变量): 从属于对象,自动初始化, 位于方法外部, 类的内部, 从属于对象, 生命周期伴随对象始终
静态变量(类变量): 从属于类, 使用static定义. 从属于类生命周期最长.
常量(constant)
一旦定义了值就不能再改变 用 final修饰
变量 | 规范 |
---|---|
类成员变量 | 首字母小写和驼峰原则 |
局部变量 | 首字母小写和驼峰原则 |
常量 | 大写字母和下划线 |
类名 | 首字母大写和驼峰原则 |
方法名 | 首字母小写和驼峰原则 |
数据类型
基本数据类型:
数值型
整数型(byte 1字节, short 2字节, int 4字节, long(要加L) 8字节)
浮点型(float后面要加F 4字节, double 8字节)不精确, 要精确的话使用math中的BigDecimal
字符型 (char 2字节)
布尔型 (boolean 1位)
引用数据类型 (4字节用来代表对象地址)
类
接口
数组
运算
int a = 3;
int b = a--;
// 先把a的值赋予b, 然后a再做自减
// a=2 b=3
int c = 3;
int d = --c;
// c先做自减, 然后再把值赋予d
// c=2 d=2
三元运算符
// x ? y : z
// x为boolean类型表达式,若x为true,返回y,否则返回z
boolean a = true;
String x = a ? "早上" : "晚上";
System.out.print(x);
类型转换
自动类型转换: 容量小的数据类型可以自动转换成容量大的数据类型 (虚线代表可能损失精度)
强制类型转换: (type) 要转化的数据
注意!若计算结果溢出,要在计算的时候就转化
int money = 1000000000;
int year = 20;
int total = money*year;
System.out.println("total="+total); //total=-1474836480
long total3 = (long)money*year;
System.out.println("total3="+total3); //total3=20000000000
条件选择结构
switch 在多值判断下使用
if (a<10){
// 所要做的事
}else if (a<20){
// 这里 a>10 && a<20
// 所要做的事
}else if (a<30){
// 这里 a>20 && a<30
// 所要做的事
}else{
// 所要做的事
}
int month = (int) (1 + 12*Math.random());
System.out.println("月份:"+month);
switch (month) {
case 10:
System.out.println("有国庆节");
break;
case 5:
System.out.println("有劳动节");
break;
case 1:
System.out.println("过春节");
default:
System.out.println("em....");
}
// #######################################
char letter = 'a';
int rand = (int) (26*Math.random());
char letter2 = (char) (letter+rand);
switch (letter2) {
case 'a':
case 'e':
case 'i':
case 'o':
case 'u':
System.out.println("原音");
break;
case 'y':
case 'w':
System.out.println("半元音");
break;
default:
System.out.println("辅音");
break;
循环语句
while
while (条件){
循环体
}
-----------------------------------------
public static void main(String[] args) {
int n = 1;
int sum = 0;
while (n<=100) {
sum += n;
n++;
}
System.out.println(sum); // 5050
}
for
for (初始化语句;条件判断;迭代){
循环体
}
public static void main(String[] args) {
int sum = 0;
for (int i = 1;i<=100;i++) {
sum+=i;
}
System.out.print(sum); // 5050
}
for (int i = 1,j=i+10;i<5;i++,j=i*2) {
System.out.println("i="+i+" j="+j);
}
}
都是执行初始化语句后,先进行判断,再执行循环体,然后再迭代,最后循环
// 找出素数
outer:for (int i=150;i<=200;i++) {
for(int j=2;j<i/2;j++) {
if (i%j ==0) {
continue outer; // --> 符合条件跳到第一个循环
}
}
System.out.print(i+" ");
}
方法(函数)
[修饰符1,修饰符2 …] 返回值类型 方法名(形式参数列表){
Java 语句
}
若无需返回值,需要指定返回值为void
public class Func {
public static void main(String[] args) {
Func f = new Func(); // new一个Func这个类的对象
//(若有static修饰,就不需要new)
int sum = f.add(1, 2, 3); // 调用add方法
System.out.print(sum);
}
int add(int a,int b, int c) { // add方法
int sum = a+b+c;
return sum;
}
}
参数传值机制:基本数据类型参数的传递,是传递值的副本,副本不会影响原值
方法重载(overload)
方法重载:函数名相同,但是功能不同
- 方法名相同,参数个数不同,构成重载
- 方法名相同,参数类型不同,构成重载
- 方法名相同,参数顺序(类型顺序)不同,构成重载
- 只有返回值不同,不构成重载
- 只有参数名称不同,不构成重载
// 只有返回值不同,不构成重载
public static int add(int a, int b) {
int sum = a+b;
return sum;
}
public static long add(int b, int a) {
long sum = a+b;
return sum;
// 参数名不一样,不构成重载
public static int add(int a, int b) {
int sum = a+b;
return sum;
}
public static int add(int b, int a) {
int sum = a+b;
return sum;
}
}
面向对象
类(class)
相当于模板,蓝图,系统根据类的定义来造出对象;
类的构成:
属性(field,或叫成员变量;用来定义类的实例的数据或者静态特征)
方法(method;用来定义类的实例的行为特征和功能实现)
对象(object,instance)
是类的实例
现实世界中:是客观世界中的一个实体
在计算机世界中:是一个可表示的存储区域
创建对象的过程
- 分配对象空间,并将对象成员变量初始化为0或null
- 执行属性值的初始化
- 执行构造方法
- 返回对象的地址给相关的变量
面向对象内存分析
先编译成字节码文件后,java 类名 开启Java虚拟机
Java虚拟机分为三部分:栈(stack),堆(heap),方法区(method area)
栈:
1.栈用来描述方法执行的内存模型。每个方法会创建一个栈帧(存储局部变量,操作数,方法出口等)
2.JVM为每个线程创建一个栈,用于存放该线程执行发放的信息(实际参数,局部变量)
3.栈属于私有,不能实现线程之间的共享
4.展示有系统自动分配,速度快,是连续的内存空间
5.方法执行完后,马上关闭该栈帧
堆:
1.堆用于存储创建好的对象(对象的地址,属性,方法)
2.JVM中只有一个堆,被所有线程共享
3.堆是一个不连续的内存空间,分配灵活,速度慢
方法区(包含在堆中):
1.JVM中只有一个方法区,被所有线程共享
2.用于存放程序中不变的或唯一的内容(类信息,静态变量,字符串常量等)
构造器(构造方法)
1.构造方法的名称必须和类名保持一致
2.通过new关键字调用
3.构造器虽然有返回值,但是不能定义返回数据类型(返回值的类型肯定是本类),不能在构造器中用return返回某个值
4.若没有定义构造器,编译器会自动定义一个无参数的构造函数,可自定义一个无参数的构造器
public class MethodOfConstructor {
public static void main(String[] args) {
Point p = new Point(3,4);
Point op = new Point(0,0);
double d = p.getDistance(op);
System.out.println(d); // 结果:5.0
}
}
class Point{
double x;
double y;
public Point(double _x,double _y) { // 构造方法,不需要关键字class
x = _x;
y = _y;
}
public double getDistance(Point op) {
double d = Math.sqrt(Math.pow(x-op.x, 2)+Math.pow(y-op.y, 2));
return d;
}
}
构造方法重载
构造方法的重载与方法重载相同
this
- this的本质就是“创建好的对象的地址”;this也可以表示为当前对象
- 在构造器中调用构造器,且必须位于构造方法的第一句
- this不能用于static方法中(static方法在方法区,无法找到对象)
static
static修饰的成员变量和方法,从属于类;普通变量和方法从属于对象
对象可以调用静态方法和静态变量,但是静态方法不能调用普通变量和方法
静态方法内不能含有this因为它不依附于任何对象,既然都没有对象,就谈不上this了
静态变量被所有的对象所共享,在内存中只有一个副本【存放在方法区】,它当且仅当在类初次加载时会被初始化。而非静态变量是对象所拥有的,在创建对象的时候被初始化,存在多个副本,各个对象拥有的副本互不影响。
参考内存中的 方法区 和 堆
(有汽车图纸不一定有汽车【类】,有汽车一定有汽车图纸【对象】)
面向对象的三大特征
1. 封装性
* 模块化: 将属性和行为封装在类中, 程序定义很多的
* 信息隐蔽: 将类的细节部分隐藏起来, 用户值通过受保护的接口访问某个类
2. 继承性
* 父类和子类共享数据和方法 (extends)
3. 多态性
* 不同的对象收到同一个消息(调用方法)可产生完全不同的效果
* 实现的细节则由接收对象自行决定
继承(extends)
使用关键字extends
子类继承父类的,拥有父类的属性和方法(除了父类的构造方法,私有属性和方法)
package cn.zxj.oo2;
public class TestExtends {
public static void main(String[] args) {
Student stx = new Student("zxj",22,"Computer");
stx.study();
stx.rest();
stx.say();
System.out.println(stx.nation);
// 判断该对象属不属于某一个类用 instanceof
System.out.println(stx instanceof Person); // true
System.out.println(new Student() instanceof Person); // true
System.out.println(stx instanceof Object); // true
System.out.println(new Person() instanceof Student); // false
}
}
class Person{
int age;
String name;
static String nation = "China";
public void rest() {
System.out.println("我正在休息");
work();
}
public static void work() {
System.out.println("我正在工作");
}
}
class Student extends Person { // 继承,使用关键字extends
String major;
public Student() {
}
public Student(String name, int age, String major) {
this.name = name;
this.age = age;
this.major = major;
}
public void study() {
System.out.println("我正在学习");
}
public void say() {
System.out.println("我叫"+this.name+",我今年"+this.age+"岁了,我的专业是"+this.major);
}
}
查看该类的类型层次(继承关系)选中类名 ctrl+t
Super
super用来调用父类对象的普通方法
package cn.zxj.oo2;
public class TestSuper {
public static void main(String[] args) {
// TODO Auto-generated method stub
FatherClass fc = new FatherClass();
ChildClass cc = new ChildClass();
fc.say();
cc.say();
cc.test();
}
}
class FatherClass {
public int id;
public void say() {
id = 1;
System.out.println("FC的id为:"+this.id);
}
}
class ChildClass extends FatherClass{
public int id;
public void say() {
id = 2;
super.say();
System.out.println("CC的id为:"+this.id);
}
public void test() {
System.out.println("cc的id:"+id);
System.out.println("fc的id:"+super.id);
}
}
继承时,使用构造方法时会先调用父类的构造方法
package cn.zxj.oo2;
public class TestSuper2 {
public static void main(String[] args) {
// TODO Auto-generated method stub
Fc fc = new Fc();
System.out.println("");
Cc cc = new Cc();
System.out.println("");
}
}
class Fc{
public Fc() {
System.out.println("FFFFFFFFFFFFFc");
}
}
class Cc extends Fc{
public Cc() {
System.out.println("CCCCCCCCCCCCCc");
}
}
构造方法第一句总是: super()来调用父类对应的构造方法.所以,流程上就是: 先向上追溯到Object, 然后再依次向下执行类的初始化块和构造方法, 直到当前子类为止. 静态初始化块也相同
重写(override)
方法重写要符合3个要点:
- 方法名,形参列表相同
package cn.zxj.oo2;
public class TestOverride {
public static void main(String[] args) {
Horse h = new Horse();
h.run();
}
}
class Vehicle {
public void run() {
System.out.println("running...");
}
public void stop() {
System.out.println("停止!");
}
}
class Horse extends Vehicle{
public void run() { // 重写方法
System.out.println("驾~~~");
}
}
- 返回值类型和声明异常类型,子类小于等于父类
class Vehicle {
public Person whoIsPsg() {
return new Person();
}
}
class Horse extends Vehicle{
public Student whoIsPsg() {
return new Student(); // 返回值类型小于等于父类
}
}
- 访问权限大于等于父类
封装(encapsulation)
程序设计追求“高内聚,低耦合”,高内聚:类地内部数据操作细节自己完成,不允许外部干涉,低耦合:仅暴露少量的方法给外部使用,尽量方便外部的调用
封装的实现——使用访问控制符
修饰符 | 同一个类 | 同一个包(包下的子类) | 子类 | 所有类 |
---|---|---|---|---|
private | ✔ | |||
default | ✔ | ✔ | ||
protected | ✔ | ✔ | ✔ | |
public | ✔ | ✔ | ✔ | ✔ |
public只能有一个
使用细节
- 一般使用private访问权限
- 提供相应的get/set方法来访问相关属性(可使用工具),这些方法通常是public修饰的,以提供对属性的赋值与读取操作(注意:boolean变量的get方法是is开头!)
- 一些只用于本类的辅助性方法可以用private修饰,希望其它类调用的方法用public修饰
多态(polymorphism)
- 多态是方法的多态,不是属性的多态
- 多态的存在有3个必要条件:继承,方法重写,父类引用指向子类对象
- 父类引用指向子类对象后,用该父类引用调用子类重写的方法,此时多态就出现了
package cn.zxj.Polymorphism;
public class TestPolymorphism {
public static void main(String[] args) {
Animal a = new Animal();
Dog d = new Dog();
Cat c = new Cat();
animalCry(a);
animalCry(d);
animalCry(c);
}
// 多态,父类引用指向子类对象
static void animalCry(Animal x) {
x.shout();
}
/*
* 不用多态就要重载方法
static void animalCry(Cat x){
x.shout
}
static void animalCry(Dog x){
x.shout
}
*/
}
class Animal{
public void shout() {
System.out.println("叫一声");
}
}
class Dog extends Animal{
public void shout() {
System.out.println("汪汪汪!");
}
}
class Cat extends Animal{
public void shout() {
System.out.println("喵喵喵!");
}
}
面向对象进阶
抽象方法,抽象类
抽象方法:要使用关键字abstract修饰,没有方法体,不用实现,但是子类必须实现。定义的是一种规范,让继承的子类必须实现此方法
抽象类:包含抽象方法的类为抽象类,要用abstract修饰,抽象类用来被继承,通过抽象类可以做到严格限制子类的设计。
- 有抽象方法的类只能定义成抽象类
- 抽象类不能实例化
- 抽象类可以包含属性方法,但是构造方法不能用来new实例,只能用来被子类调用
- 抽象类只能用来被继承
- 抽象方法必须被子类实现
接口
接口的本质就是规范,定义一组规则!,接口名称可以直接调用静态方法
格式:
[访问修饰符] interface 接口名称 [extends 父接口1,2..]
[public static final] 常量;
[public abstract void] 方法名称();
实例:
package cn.zxj.oob;
public class TestInterface {
public static void main(String[] args) {
Volant a = new Angel(); // 只能用fly方法
a.fly();
Honest a2 = new Angel(); // 只能用honest方法
a2.honest();
Angel q = new Angel();
q.fly();
q.honest();
Bird b = new Bird();
b.fly();
}
}
interface Volant {
int FLY_HEIGHT = 1000;
void fly();
}
interface Honest {
void honest();
}
class Angel implements Volant,Honest{
@Override
public void honest() {
System.out.println("I help others");
}
@Override
public void fly() {
System.out.println("I can fly"+FLY_HEIGHT+"m");
}
}
class GoodMan implements Honest {
@Override
public void honest() {
System.out.println("I'm a good man");
}
}
class Bird implements Volant{
@Override
public void fly() {
System.out.println("fly~~~");
}
}
接口可以多继承,类只能单继承
子类必须重写父类的方法!
package cn.zxj.oob;
public class TestInterface2 {
}
interface A{
void testa();
}
interface B{
void testb();
}
interface C extends A,B{
void testc();
}
class Emm implements C{
@Override
public void testa() {
// TODO Auto-generated method stub
}
@Override
public void testb() {
// TODO Auto-generated method stub
}
@Override
public void testc() {
// TODO Auto-generated method stub
}
}
内部类
成员内部类(非静态内部类,静态内部类)
非静态内部类
- 非静态内部类必须即存在一个外部类的对象里。
- 非静态内部类可以直接访问外部类的成员,但是外部类不能直接访问非静态内部类的成员
- 非静态内部类不能有静态方法,实行,初始化块
- 外部类的静态方法,静态代码块不能访问非静态内部类
package cn.zxj.oob;
public class TestInnerClass {
public static void main(String[] args) {
Outer.Inner inner = new Outer().new Inner();
inner.show();
/*
外部的age:10
内部的age:30
内部局部的age:20
*/
Outer ou = new Outer(); // 10
}
}
class Outer{
int age = 10;
public void show() {
System.out.println(age);
}
class Inner{
int age = 20;
public void show() {
int age = 30;
System.out.println("外部的age:"+Outer.this.age);
System.out.println("内部的age:"+age);
System.out.println("内部局部的age:"+this.age);
}
}
}
静态内部类
一定要用static修饰
package cn.zxj.oob;
public class TestInnerStaticClass {
public static void main(String[] args) {
Outer2.Inner2 i2 = new Outer2.Inner2();
i2.show();
/*
内部类的局部:20
Inner age = 30
*/
}
}
class Outer2{
int age = 10;
public void show() {
System.out.println(age);
}
static class Inner2{
int age = 20;
public void show() {
int age = 30;
System.out.println("内部类的局部:"+this.age);
System.out.println("Inner age = "+age);
}
}
}
匿名内部类
new 父类构造器/实现接口(){
// 类体
}
匿名内部类没有访问修饰符,无构造方法
package cn.zxj.oob;
public class TestAnonymityInnerClass {
public static void test(AA a) {
System.out.println("开始调用👇");
a.aa(); // 调用
}
public static void main(String[] args) {
TestAnonymityInnerClass.test(new AA() {
// 类体
@Override
public void aa() {
// TODO Auto-generated method stub
System.out.println("匿名内部类");
}
});
}
}
interface AA{
void aa();
}
参数传递机制
- 基本数据类型参数的传值
传递的是值的副本,副本改变不影响原来的值 - 引用类型参数的传值
传递的是值的副本,但是应用类型指的是“对象的地址”,副本和原参数都指向同一个地址,改变副本指向地址对象的值,原参数指向地址对象的值也被改变(内存分析)
public class TestParameterTransmit {
public static void main(String[] args) {
// TODO Auto-generated method stub
User tu = new User(100,"zxj");
System.out.println(tu.id);
System.out.println(tu.name);
System.out.println("*************");
tu.parametertransfer1(tu); // 传的是tu的地址
System.out.println(tu.id);
System.out.println(tu.name);
System.out.println("*************");
tu.parametertransfer2(tu); // 传的是tu的地址,但是tu无任何改变
System.out.println(tu.id);
System.out.println(tu.name);
System.out.println("*************");
}
}
class User{
int id;
String name;
public User(int id, String name) {
this.id = id;
this.name = name;
}
public void parametertransfer1(User u) { // 传递的是tu地址
u.id = 01;
u.name = "参数传递01"; // 改变了tu的id和name
}
public void parametertransfer2(User u) { // 传递的是tu地址
u = new User(02,"参数传递02"); // u的地址换为新的对象的地址,tu无任何改变
}
}
包管理
包名:域名倒着写,再加上模块名
同一个包内不能有同名的类
import(导入包)
- import 类(xxx.xx.x) 导入x类
- 或者在使用别的类之前说明这个类位于哪里
package pre01;
import Method.Student;
public class Welcom {
public static void main(String[] args) {
Student user1 = new Student();
Method.Student user2 = new Method.Student();
}
}
如果遇到两个同名的类可以分开用
静态导入
import static java.lang.Math.*;
常用包
包名 | 说明 |
---|---|
java.lang | Java的核心包,包括String,Math,Integer,System |
java.awt | 包含了构成抽象窗口工具集(abstract window toolkits)的多个类,用来构建和管理应用程序的图形用户界面(GUI) |
java.net | 执行与网络相关操作的类 |
java.io | 提供多种输入/输出功能的类 |
java.util | 实用工具类 |
"=="和equals
"=="代表比较双方是否相同.如果是基本类型则表示值相等, 如果是引用类型则表示地址相等(同一个对象)
equals定义为"对象内容相等"的逻辑, 可以重写equals 可借助工具
final关键字
- 修饰变量:被修饰的变量不可改变
- 修饰方法:该方法不可被子类重写,但是可以重载
- 修饰类:修饰的类不能被继承
数组
数组是相同类型的数据的有序集合。
数组是对象,数组中的每个元素相当于该对象的成员变量。
特点:
1.长度是确定的,一旦被创建就不可改变
2.数组内的元素的类型必须相同
3.数组类型可以是任何数据类型,包括基本类型和引用类型
数组的声明:
/*
type[] 数组名;
type 数组名[]
*/
int[] a1 = new int[10];
String a2[] = new String[5];
User[] a3 = new User[3];
数组的初始化:
package cn.zxj.arrays;
public class InitializeArrays {
public static void main(String[] args) {
// 静态初始化
int[] a = {1,2,3,4,5};
User[] b = {
new User(1,"qq"),
new User(2,"yy")
};
// 默认初始化
int[] c = new int[3]; //默认给数组的元素进行赋值
// 动态初始化
int[] d = new int[3]; // 动态初始化数组,先分配空间
d[0] = 10;// 再给数组元素赋值
d[1] = 20;// 再给数组元素赋值
}
}
创建数组的过程:
package cn.zxj.arrays;
public class CreateArrays {
public static void main(String[] args) {
int[] a1; // 声明数组
a1 = new int[10]; // 初始化数组(值为0/,null),给数组分配空间
for(int i=0;i<a1.length;i++) {
a1[i] = 10*i; // 给数组赋值
System.out.println(a1[i]);
}
}
}
遍历数组(for-each)
for-each是专门用来读取数组或集合中所有的元素。
注意:遍历时的数组的元素类型
/*
for(数组数据类型x: 数组a){
System.out.println(x);
}
*/
package cn.zxj.arrays;
public class Foreach {
public static void main(String[] args) {
int[] a = {1,2,3,4,5};
for(int i:a) { // 所要遍历的类型
System.out.println(i);
}
System.out.println("qqqqqqqqqqqqqqqqqqqqq");
String[] b = {"q","w"};
for(String i:b) { // 所要遍历的类型
System.out.println(i);
}
}
}
二维数组
package cn.zxj.array;
import java.util.Arrays;
public class Test2DArray {
public static void main(String[] args) {
// 一维数组
Object[] a1 = {1,"qq",91,"2018"};
Object[] a2 = {2,"yy",92,"2019"};
Object[] a3 = {3,"mm",93,"2020"};
// 二维数组
Object[][] table = new Object[3][];
table[0] = a1;
table[1] = a2;
table[2] = a3;
System.out.println(a1);
System.out.println(a2);
System.out.println(a3);
System.out.println("-------------");
for(Object[] o:table) {
System.out.println(o);
System.out.println(Arrays.toString(o));
}
}
}
静态成员不能访问非静态成员
静态与对象无关
接口
接口就是多个类的公共规范;最重要的是其中的抽象方法
接口不能有静态代码块,无构造方法
java7:接口中可以包含常量和抽象方法
java8:包含默认方法,静态方法
java9:私用方法
设置接口类
选择Interface,不能有方法体
接口中最重要的就是抽象方法,格式:
[public] [abstract] 返回值类型 方法名称(参数列表)
package cn.zxj.day02.demo01;
public interface MyInterfaceAbstract {
public void methodAbs1();
public void methodAbs2();
public void methodAbs3();
}
设置实现类
接口的使用:
- 接口不能直接使用,必须有一个实现类(子类)来实现接口
public class 实现类名称 implements 接口名称{}
- 接口的实现类必须覆盖重写接口的所有抽象方法
package cn.zxj.day02.demo01;
public class implementInterface implements MyInterfaceAbstract{
@Override
public void methodAbs1() {
System.out.println("1111111111111111111111");
}
@Override
public void methodAbs2() {
System.out.println("2222222222222222222222");
}
@Override
public void methodAbs3() {
System.out.println("33333333333333333333333");
}
}
创建对象使用实现类
package cn.zxj.day02.demo01;
public class Demo01Interface {
public static void main(String[] args) {
implementInterface i = new implementInterface();
i.methodAbs1();
i.methodAbs2();
i.methodAbs3();
}
}
默认方法
有的时候接口会升级,但是其他的实现类就会报错,因为没有重写,那么,如何保证实现类不报错的同时,接口再添加其他方法
默认方法可以被实现类直接调用
这时候就有了默认方法默认方法有方法体
[public] default void 方法名(){方法体}
如果实现类重写了默认方法,那么调用的时候就会使用实现类中重写的默认方法;如果实现类中没有重写,那么直接调用接口类中的默认方法
接口的静态方法
[public] static 返回值类型 方法名称(参数列表) {方法体}
接口名称直接调用静态方法,不能通过实现类对象调用静态方法
接口的私有方法(1.9)
接口类中想用一个公有方法来解决两个默认方法之间重复代码的问题,但是这个共有方法不应该让实现类使用,这就得私有化
- 普通私有:解决多个默认方法之间重复代码问题
private 返回值类型 方法名(参数列表){方法体}
- 静态私有:解决多个静态方法之间重复代码问题
private static 返回值类型 方法名(参数列表){方法体}
接口中的常量
格式
public interface final 类型 常量名 = 值;
接口的继承
- 一个类的父类是唯一的,但是可以实现多个接口(多继承类似)
- 实现类所实现的多个接口中,若存在重复的抽象方法,那么只需要覆盖重写一次
- 若实现类中不想重写某个方法,那么就要把这个类设置为抽象类
- 若存在重复的默认方法,那么实现类一定要对冲突的默认方法进行覆盖重写
- 若父类中的方法和接口中的默认方法发生冲突,优先使用父类中的方法
多态
多态就是父类引用指向子类对象
Fu obj = new Zi()
若子类重写了父类方法,优先使用子类的,若无则向上查找
访问成员变量:
直接通过对象名称访问成员变量:等号左边是谁优先使用谁,若无向上查找
间接通过成员方法访问成员变量:该方法属于谁,优先使用谁,若无向上查找
总结:若子类有重写,优先用子类(除了成员变量)
成员变量:编译看左边,运行还看左边
成员方法:编译看左边,运行看右边
对象的转型
- 向上转型:
父类名称 对象名 = new 子类名称()
使用父类的方法,会先去找子类的这个方法
- 向下转型
对象名无法直接操作子类中特有的方法,所以要想对象转型
子类名 对象名 = (子类名) 父类对象
安全转型
在转型的时候判断一下(instanceof)
if 父类引用 instanceof 子类名
匿名内部类
如果接口的实现类(或者是父类的子类)只需要使用唯一的一次
那么就可以省略该类的定义,而改为使用【匿名内部类】
格式:
public static void main(String[] args) {
testanony t = new testanony() {
@Override
public void method1() {
System.out.println("hahahah");
}
};
t.method1();
}
Map
其他的一些基本操作
遍历键值
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class testMap {
public static void main(String[] args) {
Map<String, Integer> map = new HashMap<>();
map.put("one",1);
map.put("two",2);
map.put("three",3);
System.out.println(map);
Set<String> keys = map.keySet();
System.out.println(keys);
for (String key : keys) {
int value = map.get(key);
System.out.println(value);
}
System.out.println("-------------------------------");
Set<Map.Entry<String, Integer>> entrySet = map.entrySet();
for (Map.Entry<String, Integer> stringIntegerEntry : entrySet) {
String key = stringIntegerEntry.getKey();
Integer value = stringIntegerEntry.getValue();
System.out.println("key:"+key);
System.out.println("value:"+value);
}
}
}
Collections
Collections.sort(list)
排序
Collections.shuffle(list)
洗牌
Collections.addAll(list, element)
添加元素,一次性添加多个
Collections.sort(list, Comparator)
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
public class test {
public static void main(String[] args) {
// ArrayList<Person> pall = new ArrayList<>();
// pall.add(new Person("zxj1",52));
// pall.add(new Person("zxj2",22));
// pall.add(new Person("zxj3",31));
// System.out.println(pall);
// Collections.sort(pall);
// System.out.println(pall);
ArrayList<String> al = new ArrayList<>();
Collections.addAll(al,"a","b","c");
}
}
class Person implements Comparable<Person> {
private String name;
private int age;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public int compareTo(Person o) {
// return this.getAge() - o.getAge(); // 升序
return o.getAge() - this.getAge(); // 降序
}
}
异常
Java异常处理的5个关键字:try,catch,finally,throw,throws
throws
把异常交给机器去处理,不用自己手动处理
throws关键字必须写在方法声明处
thorws关键字后面声明的异常必须是Exception或者是Exception的子类
import java.io.FileNotFoundException;
import java.io.IOException;
public class throwsTest {
public static void main(String[] args) throws IOException{
readFile("asdfs.mat"); // 上面要声明异常
}
public static void readFile(String fileName) throws IOException {
if (!fileName.endsWith(".txt")){
throw new FileNotFoundException("文件错误");
}else {
System.out.println("666666666666");
}
}
}
用throws异常处理后,程序如果异常就会直接停下来,不会继续后面的代码
捕获异常try…catch
格式
try{
可能产生异常的代码
}catch(定义一个异常的变量,用来接收try中抛出的异常对象){
异常的处理逻辑,一般在工作中,会把异常的信息记录到一个日志中
}catch(异常类名 变量名){
}
异常处理的三个方法
package cn.zxj.yichang;
import java.io.FileNotFoundException;
import java.io.IOException;
public class testtrycatch {
public static void main(String[] args) {
try {
readFile("asf.t");
}catch (IOException ioe){ // try中抛出什么异常对象,catch就定义什么异常变量,用来接收这个异常对象
ioe.printStackTrace();
System.out.println("-----");
System.out.println(ioe.toString());
System.out.println("-----");
System.out.println(ioe.getMessage());
}
}
public static void readFile(String fileName) throws IOException {
if (!fileName.endsWith(".txt")){
throw new FileNotFoundException("文件错误");
}else {
System.out.println("666666666666");
}
}
}
finally
有一些代码无论异常是否存在,都要执行,所以要用到finall
Lambda
将原本的匿名内部类改造一下,new xxx() 用 (参数列表)->{要输出的内容}代替
例子
接口类:
package cn.zxj.yichang;
public interface Cook {
public abstract void makeFood();
}
package cn.zxj.yichang;
public class testLambda1 {
public static void main(String[] args) {
// 匿名内部类
invokeCook(new Cook() {
@Override
public void makeFood() {
System.out.println("吃吃吃吃吃饭");
}
});
System.out.println("-----------------");
// lambda函数表达式
invokeCook(()->{
System.out.println("吃吃吃吃吃饭");
});
};
private static void invokeCook(Cook cook){
cook.makeFood();
}
}
package cn.zxj.yichang;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
public class testPerson {
public static void main(String[] args) {
Person p1 = new Person("p1",21);
Person p2 = new Person("p2",22);
Person p3 = new Person("p3",18);
ArrayList<Person> parr = new ArrayList<>();
Collections.addAll(parr,p1,p2,p3);
System.out.println(parr);
// 匿名内部类
Collections.sort(parr, new Comparator<Person>() {
@Override
public int compare(Person o1, Person o2) {
return o1.getAge()-o2.getAge();
}
});
System.out.println(parr);
System.out.println("-------------");
// lambda表达式
Collections.sort(parr,(Person o1,Person o2)->{
return o1.getAge()- o2.getAge();
});
System.out.println("lambda:"+parr);
parr.sort((Person o1,Person o2)->{
return o1.getAge()- o2.getAge();
});
}
}
函数式接口
有且只有一个抽象方法的接口,称之为函数式接口,当然接口中可以包含其他的方法
@FunctionalInterface
在接口类上面写,用来检测接口是否是一个函数式接口
package cn.zxj.yichang;
public class someInterface {
public static void show(MyfuncInterface mi){
mi.method1();
}
public static void main(String[] args) {
show(new MyfuncInterface() {
@Override
public void method1() {
System.out.println("用匿名函数调用");
}
});
show(()->{
System.out.println("用lambda调用");
});
}
}
流
package cn.zxj.day05;
import java.util.ArrayList;
import java.util.Collections;
import java.util.stream.Stream;
public class testStream2 {
public static void main(String[] args) {
ArrayList<String> t1 = new ArrayList<>();
Collections.addAll(t1,"Bob","Alex","Mogen","Davi");
ArrayList<String> t2 = new ArrayList<>();
Collections.addAll(t2,"赵一","钱二","孙三","李四");
Stream<String> stream1 = t1.stream().filter(name -> name.length()==4);
Stream<String> stream2 = t2.stream().skip(2);
Stream<String> stream3 = Stream.concat(stream1,stream2);
Stream<Person> sp = stream3.map(name -> new Person(name));
sp.forEach(person -> System.out.println(person.getName()));
}
}