基础语法
注释
//单行注释 /* 多行注释 */ /** *@Description 文档注释 */
标识符
abstract | assert | boolean | break | byte |
---|---|---|---|---|
case | catch | char | class | const |
continue | default | do | double | else |
enum | extends | final | finally | float |
for | goto | if | implements | import |
instanceof | int | interface | long | native |
new | package | private | protected | public |
return | strictfp | short | static | super |
switch | synchronized | this | throw | throws |
transient | try | void | volatile | while |
标识符以大小写字母或者$和_开头
数据类型
基本类型:
数值类型
整数类型:byte\short\long\int
浮点类型:float\double
字符类型:char
boolean类型:true和false
引用数据类型:类、接口、数组
进制:二进制0b 十进制 八进制0 十六进制0x
制表符:\t
换行:\n
*数字之间可以使用下划线分割
int num = 10;
long num1 = 300L;
float num2 = 40.1F;
double num3 = 40.12344;
char name = 'A';//只能一个字符
String name1 = "hahaha";//不是关键字,是一个类
boolean flag = true;//布尔值默认是false
类型转换
byte,short,char->int->long->float->double
不能对布尔值进行转换
//强制类型转换:高->低(可能存在溢出、精度问题)
int a = 10;
byte i = (byte)a;//a是int类型
//自动类型转换:低->高
变量、常量、作用域
每个变量必须声明类型,以分号结束。
//数据类型 变量名 = 值;可以使用逗号隔开来声明多个同类型变量
type varName [=value][{,varName[=value]}];
局部变量:使用前必须声明和初始化值
常量:设定后不能改变(大写字母下划线)
//变量类型 变量名 = 值
Demo demo = new Demo();
System.out.println(demo.name);
//常量
final static double PI=3.14;//修饰符不分顺序
基本运算符
算数运算符:+、-、*、/、%、++(自增)、--(自减)
赋值运算符:=
关系运算符:>、<、>=、<=、==、!=
逻辑运算符:&&、||、!(与或非)
位运算符:<<、>>
条件运算符: ?:
//先赋值,后自增
b = a++;
//先自增,后赋值
b = ++a;
//字符串连接符:把a和b连接起来
System.out.println("" + a+b);
//如果x是true,结果是y,否则是z
x?y:z;
Math运算
幂运算:Math.pow(底数,指数)
包机制
区别类名的命名空间
package pkg1[.pkg2[.pkg3...]];
import package1[];//import必须在下
import package1.*//通配符,导入package1下的所有
JavaDoc生成文档
生成自己的API文档
参数信息:
@author 作者名
@version 版本号
@since 需要最早使用的jdk版本
/**
* @author hello
* @version 9.18.0
* @since 1.8
*/
public class Main {
String name;
/**
*
* @param name
* @return
* @throws Exception
*/
public String test(String name) throws Exception{
return name;
}
}
流程控制
用户交互Scanner
获取用户输入:next()读取到有效字符串后结束输入、不能得到带有空格的字符串;nextLine()按下回车键之前的所有字符
//创建一个扫描器对象
Scanner scanner = new Scanner(System.in);
System.out.println("使用nextLine方式接收:");
//判断用户是否输入字符串
if(scanner.hasNextLine()){
//使用next方式接收
String str = scanner.nextLine();
System.out.println("输出的内容为:": +str);
}
//关闭
scanner.close();
练习1
import java.util.Scanner;
//输入多个数字求和与平均数,输入一个数字用回车确认,输入非数字结束输入并输出
public class Main {
public static void main(String[] args){
Scanner scanner = new Scanner(System.in);
double sum = 0;
int m = 0;
while(scanner.hasNextDouble()){
double x = scanner.nextDouble();
m++;
sum += x;
}
System.out.println(m +"个数的和为:"+sum);
System.out.println(m +"个数的平均值是:"+(sum/m));
scanner.close();
}
}
顺序结构
一步一步执行
选择结构
if
if(布尔表达式){
}else if{
}else{
}
if(s.equals("Hello"))//equals:判断字符串是否相等
switch
判断一个变量与一系列值中某个值是否相等,每个值称为一个分支
switch(expression){
case value:
//语句
break;//可选:不加break会输出剩下的
default://可选
//语句
}
循环结构
while循环
布尔表达式为true就会一直进行下去,先判断后执行
while(布尔表达式){
//表达式
}
do while循环
循环至少进行一次,先执行后判断
do{
//代码语句
}while(布尔表达式);
for循环
循环执行的次数在执行前确定
初始化语句可以是空的
for(初始化,条件,迭代)
{
//代码语句
}
//增强for循环
for(声明语句:表达式)
{
//代码句子
}
练习2
//计算0-100奇数和偶数的和
public class Main {
public static void main(String[] args) {
int oddSum = 0;
int evenSum = 0;
for(int i = 0;i <= 100;i++)
{
if(i % 2 == 0)
{
evenSum += i;
}
else
oddSum += i;
}
System.out.println(oddSum);
System.out.println(evenSum);
}
}
练习3
//使用while或for循环输出1-1000之间能被5整除的数,每行输出3个
public class Main {
public static void main(String[] args) {
int i = 1;
while(i <= 1000)
{
if(i%5 ==0) {
System.out.print(i+"\t");
}
if(i%(5*3) == 0){
System.out.print("\n");
}
i++;
}
System.out.print("\n");
System.out.println("while循环结束");
for(int a = 1;a <= 1000;a++)
{
if(a % 5 == 0)
{
System.out.print(a+"\t");
}
if(a % (5*3) == 0){
System.out.print("\n");
}
}
System.out.print("\n");
System.out.println("for循环结束");
}
}
练习4
//打印九九乘法表
public class Main {
public static void main(String[] args) {
int count = 0;
for(int i = 1;i <= 9;i++)
{
for(int j = 1;i <= 9;j++)
{
count = i*j;
System.out.print(j+"*"+i+"="+count+"\t");
if(j == i)
{
System.out.print("\n");
break;
}
}
}
}
}
练习5
//增强for循环:输出数组中的数
public class Main {
public static void main(String[] args) {
int[] numbers = {10,20,30,40,50};
//遍历数组中的元素
for(int x:numbers)
{
System.out.println(x);
}
}
}
break、continue、goto
break:在循环语句主体部分,强行退出循环
continue:终止某次循环过程,跳过尚未执行的语句,接着进行下一次是否执行的循环判定
goto:带标签的break和continue(标签:后面跟着一个冒号的标识符)
//打印出0-100之间的所有质数
public class Main {
public static void main(String[] args) {
int count = 0;
out: for(int i = 2 ;i < 100;i++)
{
for(int j = 2;j <= i/2;j++)
{
if(i % j == 0) {
continue out;
}
}
System.out.print(i+" ");
}
}
}
打印三角形以及debug
debug:在代码上打断点,查看运行过程
//打印空心三角形
public class Main {
public static void main(String[] args) {
for (int i = 1; i <= 6; i++)
{
if(i != 6)
{
for (int j = 5; j >= i; j--)
{
System.out.print(" ");
}
System.out.print("*");
for (int a = 0; a < 2*(i - 2)+1; a++) {
System.out.print(" ");
}
if (i != 1) {
System.out.print("*");
}
System.out.print("\n");
}
else {
for(int j = 1;j < 2*i;j++)
{
System.out.print("*");
}
}
}
}
}
JAVA方法
语句的集合,执行一个功能(其他语言的函数)
在程序中创建,在其他地方被调用
修饰符 返回值类型 方法名(参数类型 参数名){
方法体
return 返回值;
}
形式参数:定义作用
实际参数:实际调用
值传递和引用传递:java都是值传递
public static void main(String[] args){
int sum = add(1,2);
}
public int add(int a,int b)
{
return a+b;
}
重载
在一个类中,有相同的函数名称,但是形参不同的函数
规则:
方法名称必须相同
参数列表必须不同
返回值类型可以相同也可以不同
仅返回类型不同不是方法重载
public static int max(int a,int b)
public static double max(double a,double b)
public static int max(int a,int b,int c)
//名字一样,参数不一样或者类型不一样
命令行传参
传递命令行参数给main()函数实现,在代码保存的文件夹cmd命令行,进入正确的路径后输入需要运行的文件名以及传递的参数,回车执行
public class Main {
public static void main(String[] args) {
for(int i = 0;i < args.length;i++)
{
System.out.println("args["+i+"]:"+args[i]);
}
}
}
可变参数
在方法声明中,在指定参数类型后加一个省略号
可变参数必须在最后一项
public void test(int... i){
System.out.println(i[0]);
}
递归
自己调用自己
//阶乘
public class Main {
public static void main(String[] args) {
System.out.println(f(4));
}
public static int f(int n){
if(n == 1){
return 1;
}
else {
return n*f(n-1);
}
}
}
练习6
//计算器:使用方法、switch等
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
double result = 0;
Scanner scanner = new Scanner(System.in);
System.out.print("输入第一个数:");
double num1 = scanner.nextDouble();
System.out.print("请输入操作符:");
String operator = scanner.next();
System.out.print("输入第二个数:");
double num2 = scanner.nextDouble();
switch(operator){
case "+":
result = plus(num1,num2);
break;
case "-":
result = delay(num1,num2);
break;
case "*":
result = multi(num1,num2);
break;
case "/":
result = division(num1,num2);
break;
default:
System.out.println("输入操作符错误");
return;
}
System.out.println(result);
}
public static double plus(double a,double b){
return a+b;
}
public static double delay(double a,double b){
return a-b;
}
public static double multi(double a,double b){
return a*b;
}
public static double division(double a,double b){
return a/b;
}
}
数组
相同类型数据的有序集合,用数组下标访问
声明和创建
必须先声明
变量的类型 变量名= 变量值
//声明数组
int[] nums;
int nums[];
//创建数组
nums = new int[10];
//赋值
nums[0] = 1;
//输出
System.out.println(nums[i]);
//数组的长度
len = nums.length;
三种初始化以及内存分析
静态、动态、默认
//声明数组
int[] nums;
int nums[];
//创建数组
nums = new int[10];
//赋值
nums[0] = 1;
//输出
System.out.println(nums[i]);
//数组的长度
len = nums.length;
下标越界
数组一旦被创建,大小不可修改。
元素必须相同类型,不可混合类型。
下标合法区间:0~length-1
数组的使用
for-each循环
数组作为方法入参
数组作为返回值
//打印所有元素
for(int i = 0;i < a.length;i++){
Sytem.out.println(a[i]);
}
//增强的for循环:array是数组arrays的每一个元素
for(int array:arrays){
System.out.println(array);
}
多维数组
int[][] array = {{1,2},{2,3}}
Arrays类
直接使用类名进行调用
//打印数组元素Arrays.toString
System.out.println(Arrays.toString(a));
//数组排序Arrays.sort
System.out.println(Arrays.sort());
//ctrl+对应方法查看源码
冒泡排序
时间复杂度O(n²)
下一轮可以少一次排序
import java.util.Arrays;
public class Main {
public static void main(String[] args) {
int[] a = {1,4,2,7,4,3};
int[] sort = sort(a);
System.out.println(Arrays.toString(sort));
}
public static int[] sort(int[] array){
int temp = 0;
for(int i = 0; i < array.length-1;i++){
for(int j = 0;j < array.length-1;j++){
if(array[j] < array[j+1]){
temp = array[j];
array[j] = array[j+1];
array[j+1] = temp;
}
}
}
return array;
}
}
稀疏数组
数组中很多值是0或者没有意义的数据,用稀疏数组
大部分元素是0,记录数组有几行几列,有多少不同的值
把具有不同值的元素和行列即值记录在一个小规模的数组中,缩小程序规模
import java.util.Arrays;
public class Main{
public static void main(String[] args){
//创建一个11*11的数组,0:没有棋子,1:黑棋,2:白棋
int[][] array1 = new int[11][11];
array1[1][2] = 1;
array1[2][3] = 1;
//输出原始数组
System.out.println(Arrays.toString(array1));
for(int[] ints : array1){
for(int anInt : ints){
System.out.print(anInt+"\t");
}
System.out.println();
}
//转换为稀疏数组来保存
//获取有效值的个数
int sum = 0;
for(int i = 0;i < array1.length-1;i++)
{
for(int j = 0;j < array1.length-1;j++)
{
if(array1[i][j] != 0)
{
sum++;
}
}
}
System.out.println("有效值个数:"+sum);
int[][] array2 = new int[sum+1][3];
array2[0][0] = 11;//几行
array2[0][1] = 11;//几列
array2[0][2] = sum;//几个有效值
//将非零的值存放在稀疏数组中
int count = 0;
for(int i = 0;i < array1.length;i++)
{
for(int j = 0;j < array1.length;j++)
{
if(array1[i][j] != 0)
{
count++;
array2[count][0] = i;
array2[count][1] = j;
array2[count][2] = array1[i][j];
}
}
}
//输出稀疏数组
for(int i = 1;i < array2.length;i++)
{
System.out.println(array2[i][0] + "\t"
+ array2[i][1] + "\t"
+ array2[i][2] + "\t");
}
//还原数组
int[][] array3 = new int[array2[0][0]][array2[0][1]];
for(int i = 1;i < array2.length;i++)
{
array3[array2[i][0]][array2[i][1]] = array2[i][2];
}
System.out.println("输出还原数组");
for(int[] ints : array3){
for(int anInt : ints){
System.out.print(anInt+"\t");//不换行用print
}
System.out.println();
}
}
}
面向对象OOP
以类的方式组织代码,以对象的组织(封装)数据
三大特性:封装、继承、多态
静态static方法调用:直接写方法名调用
非静态:实例化这个类,new 类名.方法名();或者 对象类型 对象名 = 对象值;
类与对象的创建
一个项目应该只有一个main方法
非静态类是抽象的需要实例化之后调用
public class Main{
public static void main(String[] args){
//实例化非静态类Student
student.xiaoming = new Student();
Student xiaohong = new Student();
xiaoming.name = "小明";
xiaoming.age = 3;
//赋值的就按照赋值输出,没有赋值的字符串默认null整数默认0
System.out.println(xiaoming.name);
System.out.println(xiaoming.age);
}
}
public class Main{
public static void main(String[] args){
//实例化非静态类Student
student.xiaoming = new Student();
Student xiaohong = new Student();
xiaoming.name = "小明";
xiaoming.age = 3;
//赋值的就按照赋值输出,没有赋值的字符串默认null整数默认0
System.out.println(xiaoming.name);
System.out.println(xiaoming.age);
}
}
构造器
一个类即便什么都不写也会存在一个方法
特点:
必须和类的名字相同
必须没有返回类型,也不能写void
使用new关键字必须要有构造器
一旦定义了有参构造,无参构造必须显示定义
alt+insert:直接生成构造器
public class Person{
String name;
public Person(){
//实例化初始值
this.name = "ahhaha";//this:当前类
}
}
创建对象内存分析
import java.util.Arrays;
public class Main{
public static void main(String[] args){
//实例化非静态类Pet
Pet dog = new Pet();
dog.name = "旺财";
dog.age = 3;
dog.shout();
System.out.println(dog.name);
System.out.println(dog.age);
}
}
public class Pet {
String name;
int age;
public void shout(){
System.out.println("叫");
}
}
封装
属性私有:get\set
避免不合法数据,提前规避
import java.util.Arrays;
public class Main{
public static void main(String[] args){
Student s1 = new Student();
s1.setName("ahhah");
System.out.println(s1.getName());
}
}
public class Student {
private String name;//属性私有
private int id;
//提供一些public的get或者set方法
public String getName(){
return this.name;
}
public void setName(String name){
this.name = name;
}
//alt+insert生成getter和setter
}
继承
某一批类的抽象
extends扩展,子类是父类的扩展,子类有父类的所有方法
java中类只有单继承没有多继承
private finall无法继承
ctrl + h:打开继承树
所有类默认直接或者间接继承object类
public class Person {
private int money = 10_0000_0000;
public void say(){
System.out.println("说了一句话");
}
public int getMoney(){
return money;
}
public void setMoney(int money){
this.money = money;
}
}
public class Student extends Person{
}
import java.util.Arrays;
public class Main{
public static void main(String[] args){
Student student = new Student();
student.say();
System.out.println(student.money);
}
}
super
super调用父类的构造器必须在子类的第一行
只能出现在子类的方法或者构造方法中
super和this不能同时调用构造方法
和this的不同:
代表的对象不同,super父类应用,this本身
前提:this没有继承也可以用,super只能在继承才可以使用
构造方法:this子类的,super父类的
import java.util.Arrays;
public class Main{
public static void main(String[] args){
Student student = new Student();
student.test("haha");
}
}
public class Student extends Person{
private String name = "haha";
public void test(String name){
System.out.println(name);
System.out.println(this.name);
System.out.println(super.name);
}
}
public class Person {
protected String name = "yes";
}
方法重写
@Override
静态方法的调用只和左边的类型有关
非静态方法的调用子类重写父类的方法
只能是public可以重写
注意:
方法名必须相同
参数列表必须相同
修饰符:范围可以扩大不能缩小
public > protected > default > private
抛出的异常:可以被缩小,不可以被扩大
import java.util.Arrays;
public class Main{
public static void main(String[] args){
//方法的调用只和左边的类型有关
A a = new A();
a.test();
//父类的引用指向了子类
B b = new A();
b.test();
}
}
//子类
public class A extends B{
public static void test(){//如果没有static那么两个输出都是A=>test:子类重写父类的方法
System.out.println("A=>test");
}
}
//父类
public class B {
public static void test(){
System.out.println("B=>test");
}
}
多态
多态是方法的多态,属性没有多态
父类和子类有联系
static方法不能被重写
final修饰的不能被重写
private不能被重写
存在的条件:
有继承关系
方法需要重写
父类引用指向子类对象
import java.util.Arrays;
public class Main{
public static void main(String[] args){
//一个对象的实际类型是确定的
//可以指向的引用类型就不确定了:父类的引用指向子类
Student s1 = new Student();
Person s2 = new Student();
Object s3 = new Student();
//左边有的才能引用,比如不能出现s2.eat()因为父类没有eat方法
s2.run();//子类重写了父类的方法,执行子类的方法
s1.run();
}
}
public class Person {
public void run(){//没有static,不是静态类,可以重写父类方法
System.out.println("son");
}
}
public class Student extends Person{
public void run(){
System.out.println("son");
}
public void eat(){
System.out.println("ear");
}
}
instanceof和类型转换
instanceof:
判断是否存在父子关系
import java.util.Arrays;
public class Main{
public static void main(String[] args){
Object object = new Student();
System.out.println(object instanceof Student);//true
System.out.println(object instanceof Person);//true
System.out.println(object instanceof Teacher);//false
System.out.println(object instanceof String);//false
Person person = new Student();
System.out.println(person instanceof Student);//true
System.out.println(person instanceof Person);//true
System.out.println(person instanceof Teacher);//false
//System.out.println(person instanceof String);//编译报错:两者是平行关系
}
}
public class Teacher extends Person{
}
public class Person {
}
public class Student extends Person{
}
类型转换:
父->子 高->低(强制转换)
子->父 低->高(直接转换) 可能会丢失一些方法
Person obj = new Student();//左高右低
Student student = (Student)obj;//强制转换obj的类型为Student
student.go();//就可以使用Student的方法了
//另一种
((Student)obj).go();
Student student = new Student();
student.go();
Person person = student;
DAY4(2023.8.3):JAVA
static关键字
static只执行一次
对象一旦创建,先运行静态代码块
匿名代码块:赋初始值
静态导入包:import static java.lang.Math.random;(导入随机数)
public class Person{
{
System.out.println("匿名代码块");
}
static {
System.out.println("静态代码块");
}
public Person(){
System.out.println("构造方法");
}
public static void main(String[] args){
Person person = new Person();
}
}
/*输出结果:
静态代码块
匿名代码块
构造方法*/
抽象类abstract
用abstract修饰代码
抽象类的所有方法必须要由继承它的子类实现它的方法,除非子类也是抽象类
不能new一个抽象类,只能靠子类实现
有抽象方法的必须是抽象类,抽象类里面可以有普通方法
public abtract class Action{
//约束:只有方法的名字,没有方法的实现
public abtract void doSomething();
}
接口的定义与实现
接口interface可以多继承
普通类:只有具体实现
抽象类:具体实现和规范都有
接口:只有规范,约束和实现分离
接口里定义的都是常量
implements实现类
接口中没有构造方法所以不能被实例化
public interface User{
//接口中的所有定义都是抽象的,都需要有实现类
void run(String name);//不用写public abtract
}
//实现类
public class UserI implements User{//可以不止User一个接口,可以有多个接口,实现它的方法就行
//必须重写接口中的所有方法
public void run(String name){
}
}
N种内部类
在一个类的内部再定义一个类
一个java文件只能有一个public类,可以有多个class
种类:
成员内部类
静态内部类
局部内部类:类似于局部变量
匿名内部类
//成员内部类
public class Outer{
private int id = 10;
public void out(){
System.out.println("这是外部类方法");
}
public class Inner{
public void in(){
System.out.println("这是内部类的方法");
}
//获得外部类的私有属性
public void getID(){
System.out.println(id);//如果Inner是static静态类那么需要把id这个变量也改成static
}
}
}
public class Main{
public static void main(String[] args){
Outer outer = new Outer();
//通过外部类来实例化Inner(内部类)
Outer.Inner inner = outer.new Inner();
inner.getID();
}
}
异常
错误Error和异常Exception
检查性异常、运行时异常、错误ERROR(不是异常)
异常处理框架:当做一个对象处理
错误ERROR:JAVA虚拟机生成并抛出
Exception:
RuntimeException运行时异常
ArrayIndexOutOfBoundsException:数组下标越界
NullPointerException:空指针异常
AirthemeticException:算数异常
MissingResourceException:丢失资源
ClassNotFoundException:找不到类
捕获和抛出异常
异常处理的五个关键字:try/catch/finally/throw/throws
主动抛出异常throw:
throw new ArithmeticException();
一般在方法里使用
finally:可以不要这个,释放占用资源。【假设IO、资源、关闭】
catch
里面的参数就是想要捕获的异常
最高级:Throwable\Error\Exception。
可以有多个catch,级别越高越往下写
public class Test{
public static void main(String[] args){
int a = 1;
int b = 0;
try{//try监控区域
System.out.println(a/b);
}catch(ArithemticException e){//catch 捕获异常
System.out.println("程序出现异常");
}finally{//处理善后工作
System.out.println("finally");
}
}
}
自定义异常
继承Exception类
步骤:
创建自定义异常类
通过throw关键字抛出异常对象
在当前抛出异常的方法中处理异常,使用try-catch语句捕获并处理;否则在方法的声明处通过throws关键字指明要抛出给方法调用者的异常,继续进行下一步操作
在出现异常方法中的调用者中捕获并处理异常
//异常类
public class MyException extends Exception{
//传递数字
private int detail;
public MyException(int a){
this.detail = a;
}
//toString:异常的打印信息
public String toString(){
return "MyException{"+
"details="+detail+
'}';
}
}
//测试类
public class Main{
//可能会存在异常的方法
static void test(int a) throws MyException{
if(a> 10){
throw new MyException(a);//抛出
}
System.out.println("OK");
}
public static void main(String[] args){
try{
test(11);
}catch(MyException e){
System.out.println("MyException" + e);
}
}
}