Java简介
Java是一种强类型语言,每个变量都必须先定义才能使用,但是web前端开发中的html就是一种弱类型语言。
例如:
String a;
System.out.println(a);
其中,a没有初始化,会报错,应该改为:
String a=“dddd”;
Java中的数据类型
- 注意,long类型要在数字后面加L
- 如:long num1=234L;
- 同时,float类型要在数字后加F,和long同理
- Char类型就是单个的字符,String类型才是字符串,注意,char中可以放单个的汉字
- 引用数据类型
整型拓展内容
数据类型的转换
Java中数据类型的等级排序
从高到低为强转,从低到高为自动转换
- 强转示例:
double d = 3.14; int i = (int)d;Java中的变量、常量、作用域
变量
int num; //声明变量 num = 10; //初始化 int sum = 0; //声明并初始化 String name = null; //引用类型初始化为null变量命名规则
- 由字母、数字、$、_ 组成,不能以数字开头
- 区分大小写,遵循驼峰命名法(如 studentName)
- 不能使用 Java 关键字(如 int, class)
常量
final double PI=3.1415926 //普通常量 static final String URL = "https://example.com"; //静态常量常量的特点
- 必须显示初始化,且只能赋值一次;
- 命名规范:全大写,多个单词用下划线分隔;
普通常量和静态常量的区别
- 普通常量归属于实例对象,静态常量归属于类本身;
- 内存占用方面:每次new新对象的时候,普通变量会多一个副本,重复占用内存,而静态变量全局只存在一份,能节省内存;
- 普通常量在创建实例的时候才初始化,而静态常量在类加载的时候就已经完成了初始化
作用域
类级作用域
public class ScopeDemo { // 类级变量(静态变量) static int classNum = 10; // 类级常量(静态常量) static final String CLASS_NAME = "测试类"; public static void main(String[] args) { // 直接用类名访问,无需创建对象 System.out.println(ScopeDemo.classNum); System.out.println(ScopeDemo.CLASS_NAME); } }- 范围:整个类的大括号内、所有方法 / 代码块之外;
- 包含:
- 静态成员(static 变量、static 方法):属于类,全类共享,类加载后全程可见
- 实例成员(普通 final 常量、实例变量、实例方法):属于对象,所有实例方法内都能直接访问
对象级作用域(成员变量)
public class ScopeDemo { // 对象级普通变量 int objNum = 20; // 对象级常量(实例final常量) final String objId = "001"; public static void main(String[] args) { // 必须先new对象才能访问 ScopeDemo demo = new ScopeDemo(); System.out.println(demo.objNum); System.out.println(demo.objId); // ScopeDemo.objNum; 直接类名调用会报错 } }- 范围:每一个独立的对象,依附于new出来的实例
- 包含:无static修饰的普通变量/常量(注意,final关键词只决定该变量能否修改值,而不决定其所属作用域)
简单来说,用static修饰的即为类级作用域,而没有static修饰的即为对象级作用域
方法级作用域(局部变量)
public class ScopeDemo { public void testMethod() { // 方法级局部变量 int methodNum = 30; System.out.println(methodNum); // 方法内可访问 if(true) { System.out.println(methodNum); // 方法内子块也能访问 } } public static void main(String[] args) { ScopeDemo demo = new ScopeDemo(); demo.testMethod(); // System.out.println(demo.methodNum); 方法外无法访问,报错 } }- 范围:只作用于方法体内部,即方法大括号内,出了方法体即销毁
- 包含:方法体内部定义的变量/常量;
块级作用域(if/for/while/{}内部定义)
public class ScopeDemo { public void testBlock() { // 方法级变量 int num = 5; // for循环块级变量i for(int i = 0; i < num; i++) { System.out.println(i); // 块内正常使用 } // System.out.println(i); 循环外访问i,直接编译报错 // if代码块 if(num > 0) { String blockStr = "块内字符串"; System.out.println(blockStr); } // System.out.println(blockStr); if块外访问,报错 } public static void main(String[] args) { ScopeDemo demo = new ScopeDemo(); demo.testBlock(); } }- 范围:仅当前一对{}内有效,出块即失效
- 包含:在if/for/while的条件中定义的变量/常量
Java中的运算
++a与a++的区别
- a++是先用后赋值:如b=a++,则b先得到a的原始值,然后a在对自己进行自增运算
- ++a是先赋值后用:如b=++a,则a先进行自增运算,然后b得到a自增后的值
幂运算
- 幂运算需要用到工具类,即Math类
double pow=Math pow(2,3) //这就是计算2的3次方逻辑运算
与运算(&&)
两个变量都为真结果才为真;
或运算(||)
两个变量都为假结果才为假;
非运算(!)
结果逻辑取反;
Scanner对象
Scanner包的导入
- Scanner对象使用前要先导入Scanner包
import java.util.Scanner;创建Scanner对象
读取控制台
Scanner sc = new Scanner(System.in);System.in是系统标准输入流,绑定键盘输入 ,System.in属于java.lang包,会默认导入,不需要手动import
特点:
- 用于和用户交互,键盘输入;
- 程序运行后等待手动输入;
- 关闭只会关闭 Scanner,不会关闭 System.in 底层流。
读取字符串文本
Scanner sc=new Scanner(data);完整示例:
public class TestStringSource { public static void main(String[] args) { // 数据源:内存中的字符串,无磁盘IO String data = "张三 18 96.5"; Scanner sc = new Scanner(data); String name = sc.next(); int age = sc.nextInt(); double score = sc.nextDouble(); System.out.println(name + " " + age + " " + score); sc.close(); } }特点:
- 不需要与用户交互,这里的data是一个内存中写好的字符串类型的数据;
- sc.next()是Scanner类的方法,用于读取下一个是String类型的数据;
- sc.nextInt()用于读取下一个是Int类型的数据;
- sc.nextDouble()用于读取下一个是Double类型的数据;以此类推
读取本地txt文件
由于功能需要,这里需要额外导入两个包,分别是File包(用于表示磁盘文件)和FileNotFoundException包(用于捕获异常)
import java.io.File; import java.io.FileNotFoundException;特点:
- 可以读取本地文件
完整示例:
public class TestReadFile { public static void main(String[] args){ //1.创建文件对象,需要java.io.File File file = new File("test.txt"); Scanner sc = null; try { //2.文件构造器,会抛出文件不存在异常 sc = new Scanner(file); //逐行读取文件 while(sc.hasNextLine()){ String line = sc.nextLine(); System.out.println(line); } }catch (FileNotFoundException e){ System.out.println("File not found"); e.printStackTrace(); }finally { if(sc != null){ sc.close(); } } } }tip:这里的finally是为了防止资源占用,无论是否发生异常,在执行完try语句和catch语句后都会最后执行一次finally语句,如果把这个if语句放到try语句的末尾,则有可能不会执行(提前发生错误跳到catch语句)。
Switch语句
易懂说法:switch译为选择,switch(week)可以视作选择week这个变量,然后case是这个变量可能的值,当这个变量为这个case值的时候就执行对应的case语句
特点:
- Switch后跟变量名;
- Switch通常用了匹配一个特定的值
- case的值几乎可以是所有的基本变量类型
- 当所有case条件都不满足的时候,执行default语句
- case 后跟的即为对应的case的值
代码示例(普通Switch语句):
public class SwitchDemo1 { public static void main(String[] args) { int week = 3; switch (week) { case 1: System.out.println("星期一"); break; // 阻断穿透 case 2: System.out.println("星期二"); break; case 3: System.out.println("星期三"); break; case 4: System.out.println("星期四"); break; case 5: System.out.println("星期五"); break; case 6: System.out.println("星期六"); break; case 7: System.out.println("星期日"); break; default: // 所有值都不匹配时执行 System.out.println("无效星期"); } } }case穿透
定义:正常情况下,要在每一个case语句后加上break语句,否则会自动执行已满足条件case语句后面的所有case语句,这种情况称为case穿透;
代码示例(case穿透主动使用)
需求:一年四季中每三个月份会共用一个季节,以此为原理共用代码,刻意利用穿透
public class SwitchDemo2 { public static void main(String[] args) { int month = 4; switch (month) { case 3: case 4: case 5: System.out.println("春季"); break; // 本组最后一个case加break case 6: case 7: case 8: System.out.println("夏季"); break; case 9: case 10: case 11: System.out.println("秋季"); break; case 12: case 1: case 2: System.out.println("冬季"); break; default: System.out.println("月份错误"); } } }while循环
语法:
while(布尔表达式) { //循环体 }特点:
- 只要布尔表达式为true,循环就会一直执行
- 大多数情况是会让循环停下来的,会用一个让表达式失效的方式来结束循环
- 少部分情况需要循环一直执行,如服务器的请求响应监听
- 循环条件永远为true会造成死循环
- while先判断再执行
do while循环
语法:
do { //代码语句 }while(布尔表达式);特点:
- 与while循环类似,但是while循环不满足条件就不会进入循环,而do while循环即使是不满足循环条件也会先执行一遍do语句
- do while 先执行后判断
break和continue的区别和用法
- break和continue可以用在while 和 do while 语句中
- break是直接终止循环
- continue是跳过当前这次符合条件的循环
可变参数
定义:
可变参数允许方法同时接收任意个同类型参数(其底层逻辑就是数组,只是数组的调用简单化)
语法规则:
- 一个方法最多只能有一个可变参数;
- 可变参数必须放在参数列表最后一位,后面不能再写普通参数;
- 调用时可以不传参数、传 1 个、传 N 个同类型参数;
- 底层等价数组,方法内部可以像数组一样遍历、取值。
- 由于可变参数的底层逻辑是数组,所以在方法内部可以把它当作数组去处理
代码示例:
常规形式:
public void test (int a,Sting... strs){}可变参数搭配普通参数形式:
public class VarParamDemo2 { // 普通参数在前,可变参数在最后 public static void printInfo(String name, int age, String... hobbies) { System.out.println("姓名:" + name + ",年龄:" + age); System.out.print("爱好:"); for (String hobby : hobbies) { System.out.print(hobby + " "); } System.out.println("\n========"); } public static void main(String[] args) { // 不传爱好 printInfo("张三", 18); // 传2个爱好 printInfo("李四", 20, "篮球", "游戏"); // 传4个爱好 printInfo("王五", 19, "看书", "跑步", "听歌", "摄影"); } }可变参数=数组示例
public static void show(String... words) { for(String w : words) System.out.println(w); } public static void main(String[] args) { String[] strArr = {"A","B","C"}; show(strArr); // 合法,直接传数组 }重载方法的优先级示例
public class OverloadTest { // 数组参数 public static void test(int[] arr) { System.out.println("数组版本执行"); } // 可变参数 public static void test(int... arr) { System.out.println("可变参数版本执行"); } public static void main(String[] args) { int[] a = {1,2}; test(a); // 输出:数组版本执行 test(1,2); // 输出:可变参数版本执行 } }重载方法的优先级解释
当方法同时存在数组参数和可变参数重载时(即同名方法,一个是传入数组参数,一个是传入可变参数),采用以下调用规则:
- 传入固定个数参数/不传参数:优先匹配可变参数方法;
- 传入数组对象:优先匹配数组参数方法;