基本数据类型与基本运算
整形
- int: 内存占4个字节
- long 8个字节
- byte 1个字节
- short 2个字节
注意点
- java中没有无符号类型的数字
- 0开头头的是8进制数字
- 0x开头是16进制的数字
- 整数类型默认是int 类型,所以申明long类型的数字要在数字后面加L
浮点类型
- float (4字节)有效精度大约为6 ~ 7 位
- double(8字节)有效位数大约为15位
注意
- 浮点类型默认是double类型的数字
- 申明float类型的数字,需要在数字后面加F或者f。
char 类型
- 占2个字节
- 采用Unicode编码
- '\u’代表转义字符序列
- 转义序列在代码解析前得到处理
变量初始化:声明变量后,必须对变量进行显示的初始化,不能使用没有初始化的变量
常量:final修饰符修饰的固定的指向一块内存地址,并且只能 初始化一次
隐式数据类型转化
- char->int
- byte->short->int
- int -> float , int -> long , int->double
- long->float , long ->double
- float -> double
转换规则
- 若一个数字是double类型,另一个数字自动转化为double类型
- 若一个数字是float类型,另一个数字自动转化为float类型
- 若一个数字是long类型,另一个数字自动转化为long类型
- 其他情况都会转化为int 类型
注意:运算符连接的数字,隐式转化以后的类型要与左侧类型保持一致,否则会报错
int c = 10 + 10L;
int与long 类型不符所以会报错
强制数据类型转化
可能会带来数字精度的损失
结合赋值运算符
如 *+= , -= , /= , =
注意:如果左侧操作数与右侧数字类型不一样,会发生强制类型转化
如 int b = 10;b += 4L; 这时4L会转化为int 类型的数值
字符串
String
-
substring(a,b)可以提取子串
-
“+”拼接
-
java字符串的单个字母是不可以改变值的,但是可以改变字符串变量的引用
String str = “abcdefg”;str = str.substring(0,3) + “yes”;
-
equals() 判断字符串相等, == 判断只是判断字符串的地址是不是在同一个位置
-
空串与NULL串,str = “”,这个字符串是一个空串,长度为0,内容为空
-
读取某一位置的字符 str.charAt(int number)
StringBuilder 构建字符串
- 与String不同的是,String对象是恒定不变的,但是StringBuilder是会不断申请空间的
- 根据1所以StringBuilder对象是可以修改字符的
输入与输出
读取
- Scanner in = new Scanner(System.in);控制台输入
- in.nextInt(); 读取一个整数
- in.next();读取一个单词
- in.nextLine();读取一行
输出
- 有一个printf();与c语言用法相同
- 同时也可以使用String.format()创建一个格式化的字符串
数组
数组申明
- int[] a = new int[10]; 初始化并且分配空间
- int[] a = {1,2,3,4};
- int[]a = new int[]{1,3};
二维数组的申明
- 不规则二维数组的申明
int [][] a = new int[2][];
a[0] = new int[]{1, 2};
a[1] = new int[]{1, 2, 3};
2规则二维数组的申明
int [][] a = new int[2][3];
数组的拷贝
使用 copyOf(数组名 , 长度);
Date类 与 LocalDate类
- LocalDate类是一个静态类
- Date 是记录当前时间的类
- LocalDate类是记录当前日期的类
隐式参数与显式参数:s.fatherFun(2); 所谓隐式参数就是对象,显式参数就是后面的形式参数
基于类的访问权限
- 第一这个是对private访问权限来解释的
- private的私有数据,只有所属类的方法可以访问
public class Employee {
private String name;
public boolean equals(Employee other) {
return this.name.equals(other.name);
}
}
final实例字段
- 一般用于修饰不可变类的字段(类中方法所以方法不会改变其对象)
- final实例字段在构造对象的时候必须初始化(public final String name = “dhajskd”;)
静态字段
private static int Id ;
private int myId;
- 每一个对象都有自己的myId字段
- 所有这个类的对象共享一个Id字段
- Id字段属于类,不属于任何一个字段
静态常量
- Math类中的常量
静态方法
- 静态方法不需要实例化对象(如 Math.max())来调用,可以直接使用类名来调用
- 静态方法不能访问实例字段
- 静态方法可以访问静态字段
使用静态方法的情况:
- 方法不需要访问对象状态(所需要的参数均有参数来提供 。如Math.max())
- 方法只需要访问类的静态字段
静态工厂方法()
- 如LocalDate.now() , LocalDate.of()来构造对象
静态工厂方法构造对象有点:
- 可以得到与类名不同的构造器
- 可以返回子类
方法参数
- java总是按值调用(也就是说方法得到的是所有参数值的一个副值)
- 参数有俩种类型(基本数据类型,对象)
- 对象的副本是另一个对象引用,指向同一个内存
对象构造
重载:多个方法有相同的名字,不同的参数
默认字段初始化:构造器没有对字段初始化,那么字段数值默认为0 ,布尔值为false,对象引用为null
显示字段初始化
1通过一个方法将所有字段初始化
public class Exercise {
int id = fun();
public int fun(){
return 1;
}
}
2 在字段申明时,将其初始化
public class Exercise {
int id = 3;
}
this调用另一个构造器:
public class Exercise {
int id = 3;
private String str ;
public Exercise(String str , int id){
this.str =str;
this.id = id;
}
public Exercise(int id){
//this调用另一个构造器必须放在这个构造器首位
this("abs",id);
this.id = id;
}
public static void main(String[] args){
Exercise exercise = new Exercise(2);
System.out.println(exercise.str);
}
}
初始化块
public class Exercise {
int id = 3;
private String str ;
private static int mm;
public Exercise(){
System.out.println("构造器");
}
static {
mm = 3;
System.out.println("静态初始化块");
}
{
id = 3;
System.out.println("初始化块");
}
public static void main(String[] args){
Exercise exercise = new Exercise();
System.out.println(exercise.id);
}
}
- 静态初始化块在类加载时,进行初始化
- 初始化块在构造对象时进行初始化,在构造器之前进行初始化
包
包名
- package必须是程序中可执行的第一行代码
- package语句只能有一句
- package命名要求包含的所有字符均为小写,同时不能有特殊字符
- package可以有多层,每一层有.隔开,例如:package china.hubei.wuhan;(China是一个文件夹,hubei是china下的一个文件夹,wuhan是hubei文件夹下的一个文件夹
- package语句后面的分号不要掉。
- 包的路径符合所开发的系统模块的定义,比如生产对生产,物资对物资,基础类对基础类。
- 如果定义类的时候没有使用package,那么java就认为我们所定义的类位于默认包里面(default package)。
静态导入
import static java.lang.Math.*;
这样就可以直接写静态方法了,而不用用类名调用静态方法
//这样写就可以
System.out.println(max(2,100));
//不需要写成Math.max(2,100);
继承
super
-
super调用父类的方法
public class Father { public void fatherFun1(){ System.out.println("abced"); } private static int Id ; private int myId; } class Son extends Father { @Override public void fatherFun1() { super.fatherFun1(); System.out.println("zzptxdy"); } public static void main(String[] args) { Son s = new Son(); s.fatherFun1(); } }
-
super调用父类的构造器方法
- 显示调用
public class Father { private int a ; public Father() { } public Father(int a){ this.a = a; } } class Son extends Father { private int b; public Son (int a , int b){ super(a); this.b = b; } }
- 隐式调用:当没有显示调用父类构造器方法时,将自动调用父类的无参构造器方法
多态
- 变量可以指示多种实际类型称为多态(父类数组中有子类)
- 多态时,可以适当选用合适的方法,称为动态绑定
- 父类可以引用子类的对象(因为子类是一个父类)
final类与方法
- final类,不允许拓展子类,且final类中所有方法,自动是final方法,字端不是final字段
- final方法,不允许子类重写这个方法
- 内联:一个方法没有被重写并且很短,编译器能对这个方法就行优化处理
- 例如e.getName = e.name
instanceof:判断一个对象是否属于一个类
抽象类
- 抽象类可以包含字段和具体方法
- 含有抽象方法的类,必须申明为抽象类
- 抽象类可以不含抽象方法
- 抽象类不可以实例化,但是可以引用非抽象类的子类的对象
- 抽象类引用非抽象子类的方法,这些方法必须在抽象类中有定义
public abstract class Abstract {
private String name;
public void fun(){
System.out.println("具体方法");
}
public abstract void fun1();
}
class AbstractSon extends Abstract{
@Override
public void fun1(){
}
public static void main(String[] args){
Abstract s = new AbstractSon();
s.fun1();
}
}
Object
- equals在Object()中用于检测俩个对象的引用是否相同
- toString()
ArrayList
ArrayList<String> str = new ArrayList<>();
- 用get访问元素
- set来改变元素
对象包装器与自动装箱
- 包装器类是final类
- 装箱与拆箱是编译器完成的事情
ArrayList<Integer> number = new ArrayList<>();
number.add(3);
//相当于number.add(Inter.valueof(3));
Integer n = 3;
//这个过程完成了,对象拆箱,然后自增,然后装箱
n ++;
参数数量的可变的方法
public PrintStream printf(String format, Object ... args) {
return format(format, args);
}
printf就是一个参数可变的方法
枚举类
public enum Size {
SMALL("S") , MEDIUM("M") , LARGE("L");
private String size;
private Size(String size){
this.size = size;
}
public String getSize() {
return size;
}
}
- 枚举类本质是一个类,又可以存在构造方法和字段
- 构造必须是私有的
- 枚举类必须在第一行说明对象,且不可以new 新对象
- 常见方法
valueOf(),返回指定类中特定名字的枚举常量
toString(),返回枚举常量名字
int ordinal 返回在枚举类中的位置(从0开始计数)
接口
概念
- 接口所有方法都是public方法,同时也是抽象方法
- 接口中没有实例字段
- 接口可以包含常量,默认为(public static final)
- 可以实现静态方法
- 还可以有默认方法
属性
- 接口不能实例化对象
- 接口可以申明变量,但是变量必须引用实现这个接口的对象
- 可以用instanceof 检查一个对象是否实现了一个接口
注意点
- 默认方法不需在类中实现
- 静态方法通过接口来调用
public interface interfaceName {
public void printList();
public static void staticFun(){
System.out.println("接口可以实现静态方法");
}
public static final int a = 1;
default void defaultFun1(){
System.out.println("这是默认方法");
}
default void fun(){
System.out.println("------");
}
}
public class Exercise implements interfaceName{
@Override
public void printList() {
System.out.println("重写了接口的抽象方法");
}
public static void main(String[] args){
Exercise exercise = new Exercise();
exercise.printList();
exercise.defaultFun1();
interfaceName.staticFun();
// 接口变量引用实现这个接口的对象
interfaceName a ;
a = exercise;
// 判断对象是否实现这个接口
System.out.println(exercise instanceof interfaceName);
}
}
默认方法冲突
- 超类优先(超类提供的方法优先于默认方法)
- 接口冲突(只有俩个接口的方法名字相同就是冲突,是否是默认方法都会冲突)
- 俩个接口冲突,我们需要覆盖这个方法
回调与接口
import java.time.LocalDate;
import java.util.Random;
import static java.lang.Math.*;
import javax.swing.*;
import java.time.*;
import java.awt.event.*;
import java.awt.*;
//import java.util.Timer;
public class Exercise implements ActionListener{
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("现在的时间是" + Instant.ofEpochMilli(e.getWhen()));
Toolkit.getDefaultToolkit().beep();
}
public static void main(String[] args){
Exercise exercise = new Exercise();
Timer timer = new Timer(1000 , exercise);
timer.start();
JOptionPane.showConfirmDialog(null, "退出吗");
System.exit(0);
}
}
- java.awt.event 中有 ActionListener的接口,存在事件监听器的方法
Compartor接口
- 若实现字符串长度的比较,我们需要实现Compartor接口
- 因为String中实现的Comparable接口是按照字典序比较字符串
对象克隆(Cloneable 接口)
- Object类含有一个(protected方法的)clone
- 对象的拷贝与复制
- 对象简单的引用并没有实际进行对象的克隆
- 我们需要对对象进行特殊的处理
- 需要实现Cloneable接口,这个接口没有方法,是一个标记接口,但是不实现会抛出异常
lambda 表达式
语法形式
package lambda;
import java.util.*;
import javax.swing.*;
import javax.swing.Timer;
public class Lambdatest {
public static void main(String[] args){
String[] planets = new String[]{"gghjk","bfjkdsjkfkls","ckk"};
System.out.println(Arrays.toString(planets));
System.out.println("下面按照字典序排序");
Arrays.sort(planets);
System.out.println(Arrays.toString(planets));
System.out.println("下面按照长度排序");
Arrays.sort(planets,(first,second)->first.length() - second.length());
System.out.println(Arrays.toString(planets));
Timer timer = new Timer(1000 , event->System.out.println("时间是" + new Date()));
timer.start();
JOptionPane.showConfirmDialog(null , "quit");
System.exit(0);
}
}
-
参数 , -> , 表达式
-
没有参数,依然要提供括号
-
可以推导出参数类型的,还可以省略类型
-
只有一个参数,参数类型可以推导出,还可以省略括号
函数式接口
- 只有一个抽象方法的接口,可以提供一个lambda表达式,这种接口称为函数式接口
方法引用
package lambda;
public interface Reference {
String concant(String a , String b);
}
1 静态方法的方法引用
package lambda;
public class methodReference {
// @Override
public static String fun(String a, String b) {
return a + b;
}
public static void main(String[] args){
// Reference reference = (a,b)->methodReference.fun(a,b);
// 俩种是等价的
Reference reference = methodReference::fun;
System.out.println(reference.concant("a" , "b"));
}
}
2 对象::实例的方法引用
package lambda;
public class methodReference {
// @Override
public String fun(String a, String b) {
return a + b;
}
public static void main(String[] args){
methodReference a = new methodReference();
Reference reference = a::fun;
System.out.println(reference.concant("方法","引用"));
}
}
3构造器引用
package lambda;
public class methodReference {
// @Override
private String name;
public String fun(String a, String b) {
return a + b;
}
public methodReference() {
}
public methodReference(String name) {
this.name = name;
}
public static void main(String[] args) {
Reference reference = methodReference::new;
System.out.println(reference.concant("sdfg").name);
}
}
关于方法引用的理解
- 一个函数式接口的实现可以由lambda表达式来代替,现在lambda表达式用一个已经实现的方法来代替。通过::运算符来代替方法体表
变量作用域
public static void fun(String text , int delay){
ActionListener listener = event->{
System.out.println(text);
};
new Timer(delay,listener).start();
}
- lambda 可以捕获"text"这样的自由变量
- 自由变量的要求
- 只能引用,不能改变
- 不能在lambda表达式中有相同的命名
- 自由变量必须是最终值(不能在引用后发生改变)
- 在lambda中 this 指代生成这个lambda的方法
ublic methodReference(String name) {
this.name = name;
}
public static void main(String[] args) {
Reference reference = methodReference::new;
System.out.println(reference.concant("sdfg").name);
}
}
**关于方法引用的理解**
1. 一个函数式接口的实现可以由lambda表达式来代替,现在lambda表达式用一个已经实现的方法来代替。通过::运算符来代替方法体表
##### 变量作用域
public static void fun(String text , int delay){
ActionListener listener = event->{
System.out.println(text);
};
new Timer(delay,listener).start();
}
1. lambda 可以捕获"text"这样的自由变量
2. 自由变量的要求
1. 只能引用,不能改变
2. 不能在lambda表达式中有相同的命名
3. 自由变量必须是最终值(不能在引用后发生改变)
3. 在lambda中 this 指代生成这个lambda的方法