目录
本文属于B站学习笔记
本文视频: 点击跳转视频
JAVA安装
jdk se: https://download.oracle.com/java/17/latest/jdk-17_windows-x64_bin.exe
IDEA: https://download-cdn.jetbrains.com/idea/ideaIC-2023.1.exe
基本概念
JRE: java运行环境
JVM: java虚拟机
- 源代码必须放在src中
- 源码执行: 编码后的生成out 目录, 对应的路径下的.class文件(称为:类文件| 字节码文件)
两种输出的把区别:
- println : 会在行后加换行符
- print: 会在行不加换行符
单|双引号的区别:
- 单引号: 表示字符, 是 char类型, 只能有一个字母或数字或特殊符号
- 双引号: 表示字符串, 是 String类型, 可以有多个字母或数字或特殊符号
数据类型
基础数据类型
数据类型转换
重点是: 存储小的可以往大得转, 大的不能往小了转, 变量前加(typename) 表示强制转换,如果数据太大会丢失
// 8位 16位 32位 64位
// byte shout int long
运算符
算数运算
注意: 结果得类型为: 两个元素中存储类型最大的那种,(大小顺序:见数据类型)
一元运算符
逻辑运算
&(与 运算):(Expression1) & (Expression2) 两边都为true,则返回true
|(或 运算):(Expression1) & (Expression2) 一边都为true,则返回true
!(非 运算): (!true) => false
短路运算:(前一边的结果能够推导出整体结果,则另一边不需要执行)
- &&: false && (Expression2) Expression2 不会执行
- ||: true|| (Expression2) Expression2 不会执行
三元运算
Expression1 ? Expression2 : Expression3
- Expression1 为true: 返回 Expression2 的结果
- Expression1 为false: 返回 Expression3 的结果
注意:
Expression1 ? Expression2 ? Expression3 : Expression4 : Expression5
- Expression1 为true: 返回 Expression2 ? Expression3 : Expression2 的结果
- Expression1 为false: 返回 Expression5 的结果
流程控制
-
顺序执行
- int = 1;
- int b = 2;
-
分支执行
-
单分支: if(ture){}
-
双分支: if(Expreseesion)else{}
-
多分支:if (Expreseesion)else if (Expreseesion){} else {}
-
特殊分支(平坦流):
int n = 10; switch (n){ case 10: { System.out.println('10'); // 只要匹配成功,会继续执行2、3中的操作(会忽略校验条件) } case 20: { System.out.println('20'); break; // 执行玩分支2,跳出流程不继续往下执行。 } case 30: { System.out.println('30'); } default: { System.out.println('无法匹配时,执行default分支'); } }
如图:
-
循环
while 有条件循环
int n = 1;
while (n < 2){
System.out.println(n);
n++;
}
do…while (代码至少执行一次)
/*
do {
循环体
} while(条件表达式)
*/
int n = 1;
do {
n++;
} while (n < 1);
// n == 2, 代码先进入循环体执行一次,后进行表达式判断。
for
for (int i; i < 2; i++) {
System.out.println(i);
}
java面向对象
类和对象
- 类: 表示归纳和整理
- 对象: 表示具体的事物
/*
PS: 类名开头大写
语法:
class 类名{
特征(属性),
功能(方法)
}
创建对象的语句:
new 类名();
*/
class Cookie {
// 声明属性
// 变量类型 变量名 = 变量值
// 属性类型 属性名 = 属性值
String name; // 也可以后期赋值
int age = 20;
// 声明方法
// void 方法名(参数) {功能代码}
// 执行方法
// 对象.属性名
// 对象.方法名()
void excute(){
System.out.println('name: ' + name);
System.out.println('age: ' + age);
};
}
// 引用数据类型
Cookie c = new Cookie();
c.name = "xiaoming";
c.excute();
类
class User{
String name;
String age;
}
// 创建对象:
User user = new User();
// new 关键字, 表示创建一个具体的对象, new一次,创建一次新的对象
/*
类其实是一个:结构体
一般new 出来的对象会赋值给变量, 重复使用
变量的类型就是对象的类型。(即: 类名)
对象是将内存地址赋值给了变量, 所以变量其实引用了内存中的对象,所以称之为引用变量,
而变量的类型称之为引用数据类型。
*/
// 特殊的对象: 空对象(null),没有引用的对象,称之为空对象,关键字对象。
// 所以引用类型变量的默认取值就是null
User user2 = null;
JAVA 存储数据的内部空间:
- 元空间:又称为方法区
属性
// 属性会在构建对象的时候默认初始化,而默认初始化的值取决于属性的类型。
// byte、short、int、long =》 0
// float、 double =》 0.0
// boolean =》 false
// string =》 空字符
// 引用数据类型 =》 null
方法
/*
声明的语法: void 方法名(参数){逻辑代码}
声明的语法(补充):方法的返回值类型 [void] 方法名(参数){逻辑代码}
这里的void 表示方法的结果 => 没有结果。
*/
class User {
String name;
String age;
void excute(){
System.out.println('没有返回值,不需要结果');
};
// 这里需要执行结果, 所以返回值类型为返回结果的类型:boolean
boolean isTrue(){
if (name){
return true
};
return false;
}
}
User user = new User();
boolean status = user.isTrue();
方法传参
/*
语法: 方法名(参数1,参数2,参数3,...){}
需要注意:
1.参数个数需要匹配
2.参数类型需要匹配
3.参数顺序需要匹配
4.可变参数:
语法: 参数类型... 参数名称
注意: 如果还有其他位置参数,那么可变参数需要放在最后
JAVA中参数传递为:值传递
基本数据类型:数值
引用数据类型:引用地
*/
class User{
void sayHello(String name, int age){
System.out.println("Hello " + name + ", " + age)
};
void params(int age, String... name){
System.out.println(name)
}
}
User user = new User();
user.sayHello('xiaoming', 18);
user.params(16, 'huahua');
user.params(17, 'huihui', 'zhangsan', 'lisi');
静态属性/方法
/*
语法:
属性或方法前加上 static 关键字
先有类之后才有对象:
1.对象:可以调用类型静态属性和方法
2.类:不能使用成员属性和方法
*/
class User{
// 成员属性
String age = 18;
// 静态属性
static String name = '小明';
// 静态方法
static void sayHello(){
System.out.println('Hello')
};
// 成员方法
void test(){
System.out.println('Hello');
sayHello();
};
};
// 静态属性和方法,不需要实例化
System.out.println(User.name);
System.out.println(User.sayHello);
静态代码快和静态对象
/*
类信息加载完成后,会先自动调用静态代码块。 作用: 可以完成静态属性的初始化功能
对象准备创建时,会先自动调用代码块, 但不是静态的
*/
class User{
static {
// 静态代码块
System.out.println("静态代码块..1");
};
{
// 代码块
System.out.println("代码块...1");
};
static {
// 静态代码块
System.out.println("静态代码块..2");
};
static void test(){
System.out.println("静态方法...");
};
{
// 代码块
System.out.println("代码块...2");
};
static {
// 静态代码块
System.out.println("静态代码块..3");
};
};
// User.test(); // 不会调用代码块
new User();
package(包)
/*
基本语法: package 包完整路径;
路径中的多个包使用点(.)隔开:
java.lang.Object
package 主要功能用于分类管理;
一个类中可以没有包, 但是package不能在同一源码文件中使用多次。
命名: 为了与类名区分, 一般为小写;
一般情况下,我们都会使用类型的全名(包 + 类)
// new Date();
new java.util.Date();
*/
import
/*
import 主要用于在使用类前准备好。
import 语句只能使用 在package 后, class之前。
import 关键字可以多少次使用,导入多个类。
如果同一个包中需要导入大量的类,那么可以通过通配符星号(*)来简化操作。
如果import了不同包中相同名称的类,那么使用时还是需要增加包名
类中默认导入了 java.lang 包,所以java.lang不需要导入,可以直接使用
当前类中的其他类也不需要导入,可以直接使用。
*/
package day01;
import java.util.*;
import java.sql.Date;
new ArrayList();
// 必须使用全路径(包名 + 类名)
java.util.Date t = new java.util.Date();
构造方法
/*
构造方法: 专门用于构建对象
如果一个类中没有构造方法, 那么JVM 会提供一个公共的、无参的构造方法,方便对象调用。
基本语法:
类名(){}
1.构造方法也是方法,但是没有void 关键字。
2.方法名和类名完全相同。
3.如果类中 没有 构造方法,那么jvm 会 提供默认的构造方法方便使用。
4.如果类中 有 构造方法, 那么jvm 不会 提供默认的构造方法方便使用。
5.构造方法也是方法, 所以也可以传递参数,但是一般传递参数的目的是为了对象属性的赋值。
构造方法是在对象构建时执行, 所有代码块会优先执行。
*/
class User{
String username;
User(String name){
username = name;
System.out.println("user....");
};
{
System.out.println("代码块....1");
};
void test(){
System.out.println("test....");
};
{
System.out.println("代码块....2");
};
}
System.out.println("before....");
User user = new User("xiaoming");
System.out.println("after....");
user.test();
继承
/*
面向对象中有3个非常重要的特征: 继承、封装、多态
类中存在父子关系: 子类可以直接获取父类的 成员属性 和 成员方法。(重点:成员)
类型继承只能是单继承: 一个类只能继承一个父类, 不能存在多个父类。
一个父类可以有多个子类。
继承语法:
class 子类 extends 父类 {}
*/
class Parent{
String name = "zhangsan";
void test(){
System.out.println("test");
};
}
class Child extends Parent {
};
Child c = new Child();
System.out.println(c.name);
c.test();
super 和 this
/*
如果父类和子类中有相同的属性, 那么可以采用特殊关键字进行区分。
super & this。
super:父类
this: 当前
PS: 这两个关键字都表示的是对象, 所以在静态方法和静态代码块中是不能使用的。
*/
class Parent1 {
String name = "zhangsan";
}
class Child extends Parent1 {
String name = "xiaoming";
void test(){
// JVM 中默认this 是隐藏的,不用写。
// System.out.println(name);
System.out.println(super.name);
System.out.println(this.name);
}
}
Child c = new Child();
c.test();
子类构造父类
/*
父类对象是在子类对象创建前 创建完成, 创建子类对象前, 会调用父类的构造方法完成父类的创建。
默认情况下: 子类对象构建时, 会默认调用父类的构造方法完成父类对象的创建。 使用的是super的方式,只不过JVM 自动完成,不需要我们手动创建。
如果父类提供了构造方法, 那么JVM不会提供默认的构造方法, 那么子类应该显示调用super方法构建父类对象。
new: 只会构建一个对象
*/
class Parent1 {
String username = "zhangsan";
Parent1(String name){
username = name;
System.out.println("Parent1....");
}
};
class Child extends Parent1 {
String name = "xiaoming";
Child(){
super("lisi");
System.out.println(name);
}
};
Child c1 = new Child();
Child c2 = new Child();
Child c3 = new Child();
多态
/*
所谓的多态,其实就是一个对像在不同的场景下表现出来的不同状态和形态,我们称之为: 多态
通俗的讲: 子类对象即可以当成子类对象使用,也可以当成父类对象使用。
多态语法其实就是对对象的使用场景进行了约束。
一个对象可以使用的功能取决于引用的变量类型。
*/
class Parent1 {
void testParent(){
System.out.println("Parent1.....");
};
};
class Boy extends Parent1 {
void testBoy() {
System.out.println("Boy.....");
}
};
class Girl extends Parent1 {
void testGirl(){
System.out.println("Girl....");
}
};
Parent1 p1 = new Parent1();
p1.testParent();
// Parent1 boy = new Boy();
// boy.testBoy(); // boy 没有testBoy对象, 一个对象可以使用的功能取决于引用的变量类型。
// boy.testParent(); // Parent1 引用对象,可以调用父类成员方法
Boy boy = new Boy();
boy.testBoy();
Girl girl = new Girl();
girl.testGirl();
方法的重载
例一:
/*
一个类中, 不能重复声明相同的方法, 也不能声明相同的属性,
相同: 方法名 and 参数列表都相同,和返回值类型无关。
如果方法名相同, 参数列表(个数, 顺序, 类型)不相同, 会认为是不同的方法,只不过名称一样。
这个操作JAVA称之为:重载。
构造方法也存在方法的 重载。
*/
class User{
User(){
System.out.println("user....");
}
User(String name){
System.out.println("user: " + name);
}
void login(){
System.out.println("支付宝登录");
}
void login(String name, String pwd){
System.out.println("账户密码登录: " + name + " " + pwd);
}
void loginwx(){
System.out.println("微信登录");
}
}
// User u = new User();
User u = new User("lisi");
u.login();
u.login("zhangsan", "123465");
u.loginwx();
例二: (构造方法之间的调用)
/*
如果一个构造方法中, 想要调用其他的构造方法, 那么需要使用的特殊关键字: this
*/
class User{
User(){
// 通过this 调用自己的第二个构造方法, 并给name参数赋值
this("张三");
}
User(String name){
this(name, "男");
}
User (String name, String sex){
System.out.println(name + " " + sex);
}
}
User user = new User();
例三:
/*
基本数据类型在匹配方法是, 可以在数值不变的情况下, 矿大数据的精度。
byte 类型无法和char类型做转换, chart没有负数, byte存在负数。
byte =》 8位
short =》 16位
char =》 16位
int =》 32位
*/
static void test( byte b ){
System.out.println("bbb");
};
static void test( short s ){
System.out.println("sss");
};
static void test ( char c ){
System.out.println("ccc");
};
static void test( int i ){
System.out.println("iii");
}
// 请依次注释掉不同参数类型的test 方法
byte n = 10;
test(n); // bbb
例四:
/*
方法的重载会向上查找
A -> Object; // Java 中所以类都是Object类的子类
B -> A -> Object;
*/
public class variableType {
public static void main(String[] args) {
// A a = new B();
// test(a); // aaaa
B a = new B();
test(a); // aaaa, 不注释test(B b)方法的结果: bbb
}
static void test(A a){
System.out.println("aaaa");
};
// static void test(B b){
// System.out.println("bbbb");
// }
}
class A{
}
class B extends A {
}
方法的重写
/*
方法的重写:父类对象的方法其实主要体现通用性, 无法在特殊的场合下使用
如果子类对象需要在特殊场合下使用, 那么就需要重写方法的逻辑, 这个操作在Java中称之为方法的重写方法(方法位成员方法)
这里的重写,并不意味着父类的方法被覆盖掉, 只是当前场合不使用,
如果要使用的话,通过super关键字还是可以访问的
注意: 方法的重写要求,子类的方法和父类的方法相同,即方法名、参数列表、返回值类型都相同,
构造方法无法重写, 因为每个类的构造方法都是类名。
方法重写后的调用:
1. 一个对象能使用什么方法, 取决于引用变量的类型。
2. 一个对象能使用什么属性, 取决于引用变量的类型。
3. 一个对象的方法具体的使用(直接、间接)是需要看具体对象的。
4.一个对象的属性具体的使用是不需要具体对象的,属性在哪里声明在哪里使用。
PS:同python 的继承,就近原则, 自己有则使用自己的, 没有就取父类中查找。
*/
class Parent{
String name = "zhangsan";
void test(){
System.out.println("Parent");
}
}
class Child extends Parent {
String name = "lisi";
void test(){
System.out.println(this.name);
System.out.println(super.name);
System.out.println("child " + this.name);
}
}
Child c = new Child();
c.test();
访问权限
/*
访问权限:
public:1. 公共的, 访问权限修饰符
2.java的源码中,公共类只能有一个, 而且必须和源码文件名相同
3.main方法:main方法是由jvm调用的,jvm调用时应该可以任意调用,而不用考虑权限问题,所以 main方法为public。
java中方法的访问权限主要分为四种:(按权限大小排序,-->从小到大)
1.private: 私有的, 同一个类中可以使用。
2.(default):默认权限, 当不设定任何权限时,JVM会默认提供权限,包权限
3.protected:受保护的全年, 子类可以访问。
4.public: 公共的, 任意使用。
权限使用范围:
1.private: 同类。
2.dafault: 同类,同包(同路径)
3.protected: 同类,同包(路径),子类
4.public: 公共的
视频:1.https://www.bilibili.com/video/BV1o841187iP?p=58
2.https://www.bilibili.com/video/BV1o841187iP?p=59
*/
外部类和内部类
/*
1.java 不允许外部类使用private, protected修饰。
2.外部类:就是在源码中直接声明的类
3.内部类:类中声明的类。
使用:
内部类就是当成外部类的属性使用即可,
// 因为内部类就是当成外部类的属性使用即可, 所以需要先构建外部类对象才可以使用。
*/
class OutUser {
String name = "zhangsan";
class InnerClass {
String name = "lisi";
}
}
OutUser outclass = new OutUser();
OutUser.InnerClass innerclass = outclass.new InnerClass();
System.out.println("out class: " + outclass.name);
System.out.println("inner class: " + innerclass.name);
单例设计
class OutUser {
private static InnerClass instace;
static class InnerClass {
};
public static InnerClass getInnerClass(){
if (instace == null){
instace = new InnerClass();
return instace;
}
return instace;
};
}
OutUser.InnerClass innerclass = OutUser.getInnerClass();
OutUser.InnerClass innerclass2 = OutUser.getInnerClass();
System.out.println(innerclass == innerclass2); // == 对比的是内存地址
final
/*
final: java中提供的一种语法, 可以在数据初始化后不被修改。
final 可以修饰:
1.变量:变量的值一旦初始化后无法修改
2.属性,那么JVM无法自动进行初始化,需要自己进行初始化, 属性值不能发生变化。
示例: public String name; --> public String name = "xxxx";
3.方法,这个方法不能被子类重写。
4.类,这样的类没有子类。
5.参数,一旦修饰参数,参数就无法修改。
final不可以修饰:
1.构造方法。
一般将final修饰的变量称之为:常量, 或者叫不可变变量。
*/
final class Parent {
public final String name = "zhangsan";
public final void say(final String content){
System.out.println("parent .... " + content);
}
}
//class Child extends Parent{
// public void say(String content){
// System.out.println("child ....");
// }
//}
Parent parent = new Parent();
System.out.println(parent.name);
parent.say("123");
// parent.name = "lisi";
System.out.println(parent.name);
abstract 抽象类
/*
抽象类: 不完整的类。
语法:
abstract class 类名
因为类不完整,所以无法直接构造对象。
抽象方法: 只有声明, 没有实现的方法。
语法:
abstrct 返回类型 方法名 (参数)
抽象类无法直接构建对象, 但是可以通过子类构建对象。
如果抽象类中含有抽象方法, 那么子类继承抽象类, 需要重写抽象方法, 将方法补充完整。
final不能与abstract 同时使用。
*/
abstract class Person {
public abstract void eat (); // 不需要加{}
}
class China extends Person{
public void eat(){
System.out.println("eat ....123");
}
}
China china = new China();
china.eat();
接口
/* 所谓的接口: 可以简单的理解为规则。
语法:
interface 接口名称 { 规则属性, 规则行为 }
接口其实是抽象的。
规则的实行必须为固定值,而且不能修改。
属性和行为的访问权限必须为公共的。
属性应该是静态的
行为应该是抽象的
接口和类是两个层面的东西
接口可以继承其他接口
类的对象需要遵循接口, 在java中,这个遵循,称之为:实现。类需要实现接口,而且可以实现多个接口。
*/
// 所以接口遵循USB协议
interface USBInterface{
}
interface USBSupply extends USBInterface{
// 提供能源的接口
public void powerSupply();
}
interface USBReceive extends USBInterface{
// 接收能源的接口
public void powerReceive();
}
class Computer implements USBSupply{
// 电脑可以为接口提供能源
public USBReceive usb1; // 接收能源接口一
public USBReceive usb2; // 接收能源接口二
public void powerSupply(){
System.out.println("提供能源");
// if(usb1 != null){
// usb1.powerReceive();
// }
if(usb1 != null)usb1.powerReceive(); // 上方if语法的改写
if (usb2 != null)usb2.powerReceive();
}
}
class Light implements USBReceive{
// 电灯可以接收能源
public void powerReceive(){
System.out.println("接收能源");
}
}
Computer c = new Computer();
Light light1 = new Light();
Light light2 = new Light();
c.usb1 = light1;
// c.usb2 = light2;
c.powerSupply();
枚举
/*
枚举是哟个特殊的类, 其中包含了一组特定的对象,这些对象不会发生改变, 一般都是用大写的标识符。
枚举使用 enum 关键字使用。
枚举类会将对象放置在最前面, 那么和后面的语法需要使用分号隔开。
*/
class MyCity{
public String name;
public int code;
private MyCity(String name, int code){
this.name = name;
this.code = code;
}
public static final MyCity BEIJING = new MyCity("北京",1001);
public static final MyCity SHANGHAI = new MyCity("上海",1002);
}
enum City{
// BEIJING, SHANGHAI;
BEIJING("北京", 1001), SHANGHAI("上海", 1002);
public String name;
public int code;
City( String name, int code){
this.name = name;
this.code = code;
};
}
// System.out.println(City.BEIJING);
// System.out.println(City.SHANGHAI);
// System.out.println(City.BEIJING.name);
// System.out.println(City.SHANGHAI.code);
System.out.println(MyCity.BEIJING.name);
System.out.println(MyCity.SHANGHAI.code);
匿名类
/*
在模型场合下, 类的名字不重要, 我们指向使用类中的方法或功能。那么此时我们可以采用特殊的语法:匿名类
所谓的匿名类,就是没有名字的类,只是用一次。
*/
interface Runs {
public void run();
}
class Person implements Runs {
public void run () {
System.out.println("人跑了。。。。");
}
}
abstract class Fly {
public abstract void fly();
}
class Bird extends Fly{
public void fly(){
System.out.println("鸟飞了....");
}
}
Bird b = new Bird();
b.fly();
new Bird(){
public void fly(){
System.out.println("猪飞了");
}
}.fly();
new Bird(){
public void fly(){
System.out.println("匿名类");
}
}.fly();
new Person().run();
new Person(){
public void run(){
System.out.println("狗跑了");
}
}.run();
bean规范
作用:
1.主要用于编写逻辑
2.主要用于建立数据模型
bean设计规范要求:
1.类必须含有无参,公共的构造方法
2.属性必须私有化,然后提供公共的set、get方法。
字符串
基本操作
/*
1.拼接 -- concat 方法
2.比较, --> 比较的是字符串的byte大小
3.截断
*/
// 拼接
String s = "abc";
String s1 = 1 + s +2;
System.out.println(s1); // 1abc2
String s2 = 1 + 2 + s;
System.out.println(s2); // 3abc
String s3 = s + 1 + 2; // abc12
System.out.println(s3);
System.out.println(s.concat("123")); // abc123
// 截断, 取最后一位, 没有[:] 切片操作
String s4 = s.substring(2, 3);
System.out.println(s4); // c
s4 = s.substring(2);
System.out.println(s4); // c
// 拆分
String sl = " abc efg hij ";
String[] s5 = sl.split(" ");
for(String s_ : s5){
System.out.println(s_);
}
// 替换
String s6 = sl.replace("efg", "123");
System.out.println(s6); // abc 123 hij
// replaceAll 按re匹配规则替换
String s7 = sl.replaceAll("efg|hij", "123");
System.out.println(s7); // abc 123 123
// 去空格
String s8 = sl.trim();
System.out.println(s8); // 去首尾空格, 半角空白字符
String s9 = sl.strip();
System.out.println(s9.length()); // 去除字符串前后的全角和半角空白字符
// 大小写转换
String si = "ABC EFG A";
String s10 = si.toLowerCase(); // 全转小写
// String s10 = si.toUpperCase(); // 全转大写
System.out.println(s10);
// 查找
int s11 = si.indexOf("EFG");
System.out.println(s11); // 第一次出现的位置
int s12 = si.lastIndexOf("A");
System.out.println(s12); // 最后一次出现的位置
boolean status = si.contains("ABC"); // 判断是否包含ABC
System.out.println(status);
// 判断是否为空
String st = "";
System.out.println(st.isEmpty()); // true
StringBuilder
/*
字符串拼接大量频繁时, 使用StringBuilder会提升性能, 减少内存空间使用
*/
StringBuilder s = new StringBuilder();
System.out.println(s.toString() == ""); // true 说明s = ""
System.out.println(s == null); // false
System.out.println(s.append("abc")); // abc
System.out.println(s.insert(0, "123")); // 123abc
System.out.println(s.reverse()); // cba321
System.out.println(s.toString()); // cba321
System.out.println(s.length()); // 6
包装类
/*
等同于把一个类装进箱子
基本数据类型与包装类相对应:
byte Byte
short Short
int Integer
long Long
float Float
double Double
char Character
boolean Boolean
*/
int i = 10;
// Integer i1 = new Integer(i);
// Integer i1 = Integer.valueOf(i);
Integer i1 = i; // 自动装箱, 这三步效果相同。
// int i2 = i1.intValue();
int i2 = i1; // 自动拆箱, 这两步效果相同。
异常|捕获
/*
java 中异常主要分为两大类:
1.可以通过代码恢复正常逻辑执行的异常, 称之为运行异常: RuntimeException
2.不可以通过代码恢复正常逻辑执行的异常,称之为编译期异常: Exception
*/
// try 和 catch 关键字可以捕获异常
try
{
// 程序代码
}catch(ExceptionName e1)
{
//Catch 块
}
// 多重捕获
// try 代码块后面跟随多个 catch 代码块的情况就叫多重捕获
try{
// 程序代码
}catch(异常类型1 异常的变量名1){
// 程序代码
}catch(异常类型2 异常的变量名2){
// 程序代码
}catch(异常类型3 异常的变量名3){
// 程序代码
}
// 抛出异常
// throws 用于在方法声明中指定可能会抛出的异常类型。
// throw 用于在代码中抛出异常
// 示例:
public void readFile(String filePath) throws IOException, [RemoteException], ... {
...
}
// ps: 一个方法可以声明抛出多个异常,多个异常之间用逗号隔开。
public void checkNumber(int num) {
if (num < 0) {
throw new IllegalArgumentException("Number must be positive");
}
}
// finally 关键字用来创建在 try 代码块后面执行的代码块。
// 无论是否发生异常,finally 代码块中的代码总会被执行。
try{
// 程序代码
}catch(异常类型1 异常的变量名1){
// 程序代码
}catch(异常类型2 异常的变量名2){
// 程序代码
}finally{
// 程序代码
}
// try-with-resource 语法糖来打开资源,并且可以在语句执行完毕后确保每个资源都被自动关闭 。
// 语句中可以声明多个资源,方法是使用分号 ; 分隔各个资源
try (resource declaration) {
// 使用的资源, 资源会自动关闭
} catch (ExceptionType e1) {
// 异常块
}
// 示例1:
try(BufferedReader br = new BufferedReader(new FileReader("test.txt"))) {
...
} catch (IOException e) {
...
}
// 示例2:
try (Scanner scanner = new Scanner(new File("testRead.txt"));
PrintWriter writer = new PrintWriter(new File("testWrite.txt"))) {
...
}catch (IOException e) {
...
}
// 自定义异常
/*
编写自己的异常类时需要记住下面的几点:
所有异常都必须是 Throwable 的子类。
如果希望写一个检查性异常类,则需要继承 Exception 类。
如果你想写一个运行时异常类,那么需要继承 RuntimeException 类。
*/
// 示例:
class MyException extends Exception{
}
集合ArrayList
/*
不需要传递构造参数, 直接new就可以, 底层数组为空数组
构造参数需要传递一个int类型的值, 用于设定顶层数组的长度
构造参数需要传递一个Collection集合类型的值, 用于将其他集合中的数据放置在当前集合中
*/
ArrayList list = new ArrayList(3);
// 添加元素,
list.add("abc");
list.add("123");
list.add("efg");
// 长度超出, 底层自动做了扩容
list.add(456);
// 输出集合
System.out.println(list);
// 获取集合大小
System.out.println("集合大小: " + list.size());
// 索引取值
System.out.println("按索引取值: " + list.get(1));
// 按索引遍历
for (int i = 0; i <list.size(); i++){
System.out.println(list.get(i));
}
// 如果你不关心元素位置
for (Object obj : list){
System.out.println(obj);
}
// 修改元素
Object oldValue = list.set(1, "789");
System.out.println("修改后的集合: " + list);
System.out.println("修改前的值: " + oldValue);
// 删除元素
Object removeValue = list.remove(1);
System.out.println("删除的值: " + removeValue);
// 判断集合是否为空
System.out.println("判断集合是否为空: " + list.isEmpty());
// 两个集合合并
ArrayList list2 = new ArrayList();
list2.add("qqq");
list2.add("www");
list2.add("eee");
list.addAll(list2);
System.out.println("合并后: " + list);
// 删除指定集合中的数据
list.removeAll(list2);
System.out.println("删除指定集合中的数据: " + list);
// 清空集合
// list.clear();
// System.out.println("复制一个新集合: " + list);
// 复制一个新集合
Object b = list.clone();
System.out.println("复制一个新集合: " + b);
// ArrayList l = (ArrayList)b;
// System.out.println(l);
// 集合转换成数
Object[] c = list.toArray();
System.out.println("集合转换成数: " + c);
泛型
/*
在集合的使用过程中简化类型的判断与转换
语法:
ArrayList <类型1> list = new ArrayList();
此时list集合就只能add 类型1的对象
PS: 泛型没有多态的概念,所以多态不能和泛型一起使用
*/
class User <C> {
public C data;
}
class User2 {
}
// 基本语法使用
ArrayList <User> list = new ArrayList();
list.add(new User()); // list 只能add User类构建的对象
// 泛型和类型的区别
// User user = new User();
// user.data = new Object();
// user.data = new User2();
User <User2> user = new User();
// user.data = new User2();
// 类型存在多态, 泛型没有多态
user.data = new Object(); // 报错
比较器
/*
基于泛型实现 自定义 比较器
*/
class NumberComparator implements Comparator<Integer> {
@Override
public int compare(Integer o1, Integer o2) {
// TODO 如果一个数比第二个数要大,那么返回结果为正数,表示升序。
// return o1 - o2;
// TODO 如果一个数比第二个数要小,那么返回结果为负数,表示降序。
// return o2 - o1;
// TODO 如果一个数和第二个数相等,那么返回结果为0.
return 0;
}
}
ArrayList list = new ArrayList();
list.add(1);
list.add(3);
list.add(2);
list.sort(new NumberComparator());
System.out.println(list);
反射
class User{
public String name = "zhangsan";
public void test1(){
System.out.println("test1....");
}
}
class Child extends User {
public void test2() {
System.out.println("test2.....");
}
}
// 多态
User user = new Child();
user.test1();
// user.test2();
// 类对象
Class<? extends User> aClass = user.getClass();
// 获取类的名称
System.out.println(aClass.getName()); // 获取类的完整名称
System.out.println(aClass.getSigners()); // 获取类的名称
System.out.println(aClass.getPackage()); // 获取类的包的名称
// 获取类的父类
Class <?> superclass = aClass.getSuperclass();
System.out.println(superclass);
// 获取类的接口
Class<?>[] interfaces = aClass.getInterfaces();
System.out.println(interfaces.length);
//获取类的属性, 有权限限制,
Field f = aClass.getField("name"); // public
Field f1 = aClass.getDeclaredField("name"); // 所有权限
Field[] f2 = aClass.getFields(); // public
Field[] f3 = aClass.getDeclaredFields(); // 所有权限
// 获取类的方法, 有权限限制,
Method method = aClass.getMethod("test2"); //public
Method m2 = aClass.getDeclaredMethod("xxx"); // 所有权限
Method[] m3 = aClass.getMethods(); //public
Method[] m4 = aClass.getDeclaredMethods(); // 所有权限
// 构造方法
Constructor<? extends User> constructor = aClass.getConstructor();
Constructor<?>[] declaredConstructors = aClass.getDeclaredConstructors();
aClass.getDeclaredConstructor();
// 获取权限修饰符, 多个修饰符会融合成一个int值。
int modifiers = aClass.getModifiers();
boolean aPrivate = Modifier.isPrivate(modifiers);