JAVA基础笔记(个人向)
JAVA基础笔记(个人向)
此笔记以B站up主遇见狂神说的【狂神说Java】Java零基础学习视频通俗易懂视频来总结学习的
Java三大版本
Java SE:标准版,桌面程序,新手入门
Java ME:嵌入式开发,基本已凉
Java EE:企业级开发,web端,服务器
Java SE —> Java EE —>就业
JDK,JRE,JVM
JDK: Java Development Kit(java开发者工具)
包含JRE和JVM,增加了一些开发程序时用到的工具
JRE: Java Runtime Environment(java运行时环境)
包含JVM,有了这个就可以运行java程序
java库
JVM: Java Virtual Machine(java虚拟机)
java底层环境,实现跨平台
解释型,编译型
数据类型
| 类型 | 存储东西(栈中) | 大小/字节 | 默认值 |
|---|---|---|---|
| byte | 数据 | 1 | 0 |
| short | 数据 | 2 | 0 |
| int | 数据 | 4 | 0 |
| long | 数据 | 8 | 0 |
| float | 数据 | 4 | 0.0 |
| double | 数据 | 8 | 0.0 |
| char | 数据 | 2 | null |
| boolean | 数据 | 1 | flase |
| 引用类型:String,对象类型 | 地址,堆中存数据 | ~ | null |
内存理解

引用类型 变量名 = 实际内容
个人理解:所以==是比变量名内容(指向内容),equals是比实际内容
!注意!:
String s1 = "abc"; //若栈中有abc则将s1直接指向栈中的abc(相当于基本类型),不然才创建String对象
String s2 = new String("abc"); //直接在堆中创建String的对象并让s2指向它
类型转换
低————————————————————>高
byte,short,char—>int—>long—>float—>double
高到低强制转换
变量,作用域
long类型后加L
float类型后加f
public class Demo01 {
//类变量,关键字static
static int c=2500;
//实例变量/成员变量:从属于对象,可以不初始化值,如果不自行初始化,值为该类型的初始值
//布尔值默认为false
//除了基本类型,其他默认都为null
String name;
int age;
public static void main(String[] args) {
//局部变量,必须声明和初始化
int a=10;
System.out.println(a);
//实例变量,需实例化对象
//实例化类!!!不是方法!!!
Demo01 d1=new Demo01();
System.out.println(d1.name);
System.out.println(d1.age);
//类变量,直接用
System.out.println(c);
}
}
常量
//final 常量名(大写) = 常量值
final PI = 56;
位运算
public class BitOperation {
public static void main(String[] args) {
/*位运算
A = 0000 1011
B = 1010 0001
------------------------------------------
A&B:0000 0001 与运算,有0则0,全1则1
A|B:1010 1011 或运算,有1则1. 全0则0
A^B:1010 1011 异或运算,相同为0,不同为1
~A: 1111 0100 取反运算
~B: 0101 1110
==========================================
A = 0000 0001 = 1
B = 0000 0010 = 2
C = 0000 0011 = 3
D = 0000 0100 = 4
E = 0000 0101 = 5
F = 0000 1000 = 8
G = 0001 0000 = 16
-------------------------------------------
A<<1:0000 0010 = B 左移1位, *2
D>>1:0000 0010 = B 右移1位, /2
效率极高!!!
所以2*8——>2*2*2*2——>2<<3=16
*/
System.out.println(2<<3);
}
}
JavaDoc
javadoc命令用来生成自己的API文档
/**
* @author 作者名
* @version 版本号
* @since 指明需要最早使用的jdk版本
* @param 参数名
* @return 返回值情况
* @throws 异常抛出情况
*/
public class Doc {
public static void main(String[] args) {
}
}
命令使用:
#javadoc [参数] 文件名
#参数:-encoding UTF-8 注释的编码为utf-8
# -charset UTF-8 字符集编码为utf-8
javadoc -encoding UTF-8 -charset UTF-8 Doc.java
Scanner对象(IO流记得关闭)
next():
//next()不能接受空格,将有效字符后的空格作为结束符,用hasNext()判断是否有输入
package com.eleike.scanner;
import java.util.Scanner;
public class Demon01 {
public static void main(String[] args) {
//引入Scanner包,创建Scanner对象接受键盘输入
Scanner scanner = new Scanner(System.in);
System.out.println("请输入:");
//判断是否有输入,if判断语句可省略
if(scanner.hasNext()){
String str = scanner.next();
System.out.println("输入的是:"+str);
}
//关闭io流
scanner.close();
}
}
nextLine():
//nextLine()将回车符作为结束符,接受结束符前全部字符,用hasNextLine()判断是否有输入
package com.eleike.scanner;
import java.util.Scanner;
public class Demon02 {
public static void main(String[] args) {
//引入包
Scanner scanner = new Scanner(System.in);
System.out.println("请输入:");
//判断是否有输入,if判断可省略
if(scanner.hasNextLine()){
String str = scanner.nextLine();
System.out.println("输入的数据是:"+str);
}
//关闭io流
scanner.close();
}
}
nextInt(), nextLong(), nextFloat()...
.......判断输入类型的方法有很多...
For循环
结构
/*
for(初始值1,初始值2...;判断条件;数值变化1,数值变化2...){
内容语句...
}
*/
for(int i = 0,j = 10; i < 10; i++,j++){
System.out.println(i+","+j);
}
For-Each增强For循环(快速遍历数组集合)
package com.eleike.loop;
//快速:array.for
public class ForDemon02 {
public static void main(String[] args) {
int[] number={10,20,30,40,50};
//增强for循环
for(int x:number){
System.out.println(x); //x为数组中各元素值
}
}
}
outer标签
//100~150中的质数
package com.eleike.base;
public class OuterDemo {
public static void main(String[] args) {
//outer标签,添加标记
outer:for (int i = 100; i <= 150; i++) {
for (int j = 2; j < i/2; j++) {
if(i % j == 0) {
//跳转到outer标签位置
continue outer;
}
}
System.out.print(i+" ");
}
}
}
方法重载
方法名必须相同,形参必须不同(形参个数,类型,顺序)
命令行传参(main方法传参)
main方法也可传参
package com.eleike.method;
//命令行传参
public class Demo01 {
//main方法也可以传参
public static void main(String[] args) {
for (int i = 0; i < args.length; i++) {
//打印输出传入到main方法里的内容
System.out.println("args["+i+"]:"+args[i]);
}
}
}
编译执行文件:
E:\Project\JavaBase\src\com\eleike\method>javac -encoding utf-8 Demo01.java #注意文件路径
E:\Project\JavaBase\src> java com.eleike.method.Demo01 hello world #注意路径和包名 传入参数hello world
args[0]:hello
args[1]:world
#输出了传入的"hello world"
可变参数(形参)
package com.eleike.method;
public class Demo02 {
public static void main(String[] args) {
Demo02 demo02 = new Demo02(); //实例化类/对象,而不是方法
demo02.test(1,2,3,4,5,6,7,8,9); //传入数量不固定,但类型需相同
}
/*
可变参数,实质为数组
在指定的类型后加省略号(...)来实现
一个方法中只能有一个可变参数,且它必须为最后一个参数
*/
public void test(int a,int... i){
for (int x : i) {
System.out.println(x);
}
}
}
数组
创建
package com.eleike.array;
public class ArrayDemo01 {
public static void main(String[] args) {
//静态初始化,声明+创建+赋值
int[] sum1 = {1,2,3,4,5};
//动态初始化,声明+创建
int[] sum2 = new int[10];
//赋值
sum[0]=10;
sum[1]=11;
sum[2]=12;
}
}
Arrays类
java提供的数组类,包含操作数组的方法
package com.eleike.array;
//引入Arrays包
import java.util.Arrays;
public class ArrayDemo02 {
public static void main(String[] args) {
int[] a={1,2,3,59,64,1231,1,98,365};
//Arrays.toString()方法:打印输出数组内容
System.out.println(Arrays.toString(a));
//Arrays.sort()方法:数组排序方法,默认升序
Arrays.sort(a);
System.out.println(Arrays.toString(a));
}
}
方法还有很多,详见jdk帮助文档
经典之冒泡排序
package com.eleike.array;
//引入Arrays包
import java.util.Arrays;
public class ArrayDemo03 {
public static void main(String[] args) {
int[] a={321,54,81,56,3,5,6,1,65,1,2154,589};
sort(a);
System.out.println(Arrays.toString(a)); //Arrays.toString()方法
}
//冒泡排序
public static int[] sort(int[] arrays){
int num = 0;
//排序次数最多是数组长度-1次,即长度5的数组,排序4次即可完成
for (int i = 0; i < arrays.length-1; i++) {
//每次排序会确认一个最大或最小值,所以-i
for (int j = 0; j < arrays.length-1-i; j++) {
//前比后大交换位置,升序排序
if(arrays[j]>arrays[j+1]){
num = arrays[j];
arrays[j] = arrays[j+1];
arrays[j+1] = num;
}
}
}
return arrays;
}
}
稀疏数组(数组压缩)
当一个数组中大部分元素为0或为同一值的时候,可以使用稀疏数组来保存该数组
稀疏数组第一行存储原始数组的行,列,有效数据个数,之后每行存储有效数据的坐标(所在行和列)和值
所以稀疏数组的大小为 array[有效数据个数+1][3]
package com.eleike.array;
//稀疏数组
public class ArrayDemo04 {
public static void main(String[] args) {
//创建原始数组
int[][] array1 = new int[15][15];
array1[1][2]=11;
array1[5][1]=25;
array1[3][6]=23;
array1[9][5]=86;
array1[3][10]=6;
System.out.println("原始数组为:");
for (int[] ints : array1) {
for (int anInt : ints) {
if (anInt >= 10){
System.out.print(anInt+" ");
}else{
System.out.print(anInt+" ");
}
}
System.out.println();
}
System.out.println("===========================================");
int sum = 0; //计算原始数组有效数据个数
int sum2 = 0; //计算原始数组每列长度
int max = array1[0].length; //记录原始数组最长列
for (int[] ints : array1) {
sum2 = 0;
for (int anInt : ints) {
sum2++; //每有一个数据+1,计算列长
if (anInt != 0){
sum++;
}
}
//此列长度比以往列长,则记录此列长度
if (sum2 > max){
max = sum2;
}
}
System.out.println("有效值个数为:"+sum+"\n最长列为:"+max);
//创建稀疏数组,长度为有效数据+1,列为3
int[][] array2 = new int[sum+1][3];
//稀疏数组第一行记录原始数据的行,列,有效数据个数
array2[0][0] = array1.length;
array2[0][1] = max;
array2[0][2] = sum;
int cont = 0;
//遍历原始数组,记录每一个有效数据的坐标和值
for (int i = 0; i < array1.length; i++) {
for (int j = 0; j < array1[i].length; j++) {
if (array1[i][j] != 0){
cont++;
array2[cont][0] = i;
array2[cont][1] = j;
array2[cont][2] = array1[i][j];
}
}
}
System.out.println("转换后的稀疏数组为:");
System.out.println(" 行 |列 |值");
//打印转化后的稀疏数组
for (int i = 0; i < array2.length; i++) {
System.out.print("["+i+"] ");
for (int j = 0; j < array2[i].length; j++) {
if (array2[i][j] >= 10){
System.out.print(array2[i][j]+" ");
}else{
System.out.print(array2[i][j]+" ");
}
}
System.out.println();
}
System.out.println("===========================================");
//根据稀疏数组还原原数组
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) {
if (anInt >= 10){
System.out.print(anInt + " ");
}else{
System.out.print(anInt + " ");
}
}
System.out.println();
}
}
}
异常
- 越界异常:ArrayIndexOutofBounds
static关键字
-
被static关键字修饰的方法或者变量不需要依赖于对象来进行访问,只要类被加载了(跟类一起加载),就可以通过类名去进行访问。
-
被static修饰的变量/方法被称为静态变量/静态方法
-
!!!static关键字不会影响到变量或者方法的作用域!!!
-
初始化的顺序: 静态代码块 > 构造代码块(匿名代码块) > 构造函数
面向对象
OOP(Object-Oriented Programming):面向对象编程 OO:面向对象
面向过程:线性思维,第一步...第二步...第三步...
面向对象:物以类聚,分类思维
本质
以类的方式组织代码,以对象的方式组织(封装)数据
抽象的
三大特征
封装:封装数据,安全
继承:继承父类
多态:同一事物多种形态,不同对象执行相同方法结果不同
构造器
-
类中的构造器也称之为构造方法
-
一个类即使什么方法都不写也会有一个隐藏的默认的构造方法
-
构造方法特点:
-
package com.oop.Demo01; public class Student { /* 1.方法名必须与类名相同 2.方法没有任何返回值(!不需要void修饰!) */ public Student() { } }
-
-
构造方法作用:
- new关键字创建对象本质是调用构造方法
- 初始化对象的值
-
有参构造方法:
-
package com.oop.Demo01; public class Student { String name; //无参构造方法 public Student() { } //有参构造方法,实质是方法的重载 //创建对象时会根据传入的参数选择对应的构造方法 public Student(String name) { this.name = name; } } -
定义了有参构造方法后,如果想使用无参构造方法,那必须再显示的定义一个无参构造方法!!!
-
idea快捷键
Alt+Insert,快速创建构造方法
-
封装(数据的隐藏)
属性私有,get/set
package com.oop.Demo02;
//主调用类
public class Application02 {
//main方法,调用其他类
public static void main(String[] args) {
Person02 p1 = new Person02();
p1.setName("eleike");
p1.setAge(999);
p1.setIdCode(370104155);
System.out.println(p1.getName());
System.out.println(p1.getAge());
System.out.println(p1.getIdCode());
}
}
////////////////////////////////////////////////////////////////
package com.oop.Demo02;
/*
1.提高程序安全性,保护数据
2.隐藏代码的实现细节
3.统一接口
4.系统可维护增加了
*/
//抽象类
public class Person02 {
//private:私有的
private String name; //姓名
private int age; //年龄
private int idCode; //身份证号
//私有属性无法直接访问,所以需要提供一些public的get,set方法
//获得name数据
public String getName() {
return name;
}
//设置name数据值
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
//设置属性值的时候可以对设置的值进行判断
if (age > 120 || age < 0){ //年龄太高或太低不合理
this.age = 3;
}else{
this.age = age;
}
}
public int getIdCode() {
return idCode;
}
public void setIdCode(int idCode) {
this.idCode = idCode;
}
}
继承(extends)
构造方法不能被继承
结构
关键字extends
package com.oop.Demo03;
public class Application03 {
//主方法
public static void main(String[] args) {
Student03 std1 = new Student03();
//子类可使用继承自父类的公共属性和方法
std1.say();
System.out.println(std1.money);
std1.setName("eleike");
System.out.println(std1.getName());
}
}
////////////////////////////////////////////////////////
package com.oop.Demo03;
//父类Person
public class Person {
//私有属性或方法不能继承
private String name;
//公共属性或方法可以继承
public int money = 10_0000_0000;
//公共属性或方法可以继承
public void say(){
System.out.println("我是父类");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
////////////////////////////////////////////////////
package com.oop.Demo03;
//关键字extends
//子类Student03,继承自父类Person
public class Student03 extends Person{
}
-
java只有单继承,没有多继承,即一个子类只能有一个父类,但一个父类可有多个子类
-
所有类都会直接或间接的继承自Object类
![image-20211125225008527]()
-
IDEA快捷键(ctrl+h)查看类继承关系图
super关键字
super特点:
- super用来调用父类的属性或方法
- !!!super必须出现在子类的方法或构造方法中!!!只能写在方法中!!!
- this和super不能同时调用构造方法
与this相比:
- 前提
- this没有继承也可使用
- super只能用在有继承的子类中
- 构造方法
- this(); 本类的构造方法,可减少代码数量
- super();表示父类的构造方法
package com.oop.Demo04;
//主方法,程序入口
public class Application04 {
public static void main(String[] args) {
Student04 std4 = new Student04();
std4.say();
}
}
////////////////////////////////////////////////////////
package com.oop.Demo04;
//父类
public class Person04 {
String name;
public Person04() {
System.out.println("父类无参构造执行!");
}
public Person04(String name) {
this.name = name;
System.out.println("父类有参构造执行!");
}
public void print(){
System.out.println("This is Person!");
}
}
/////////////////////////////////////////////////////////
package com.oop.Demo04;
//子类,继承Person04
public class Student04 extends Person04{
//无参构造
public Student04() {
//隐藏代码:super()默认调用父类无参构造,要在第一行
//也可以调用父类的有参构造:super("zhangsan");
super();
//this()默认调用自身的构造方法,不能与super()同时用
System.out.println("子类无参构造执行!");
}
public void print(){
System.out.println("This is student!!!");
}
public void say(){
super.name = "Eleike"; //修改父类属性
System.out.println(super.name); //输出父类属性
this.print(); //调用自身的print()方法
super.print(); //调用父类的print()方法
}
}
子类对象创建过程是先执行父类的无参构造,再执行子类的无参构造
方法的重写
只能重写方法
构造方法不能被继承,所以也无法被重写
概念:
- 需要有继承关系,子类重写父类的方法!
- 方法名必须相同
- 参数必须相同
- 修饰符的范围可以扩大但不能缩小,修饰符范围:public>Protected>Default>private
- 抛出的异常的范围可以缩小但不能扩大
!!!重写子类的方法与父类一致,方法体不同!!!
package com.oop.Demon05;
//程序入口
public class Application05 {
public static void main(String[] args) {
Student05 std5 = new Student05();
std5.say();
}
}
///////////////////////////////////////////////////////
package com.oop.Demon05;
//父类
public class Person05 {
public void say(){
System.out.println("Person05说话了!");
}
}
//////////////////////////////////////////////////////
package com.oop.Demon05;
//子类
public class Student05 extends Person05{
//Override重写
@Override //注解,有功能
public void say() {
//重写的方法
System.out.println("Student05说话了");
}
}
为什么重写:
- 父类的功能子类不需要
- 父类的功能子类不满足
IDEA快捷键:ALT+Insert —>Override
不能重写的方法:
- static:静态方法,属于类,不属于实例
- final:常量
- private:私有方法
多态
方法的多态,没有属性的多态
概念
一个对象的实际类型是确定的,但可以指向的引用类型就不确定了(引用类型和实际类型必须要有继承关系)
//引用类型 a = new 实际类型();
Student s = new Student();
父类的引用指向子类的情况:
B继承A,A a1 = new B();
调用方法时:
- 静态方法:
- 优先调用自身引用类型内对应的方法
- 父类没有则无法调用,调用子类需强行转换成子类引用类型
- 动态方法:
- 子类没有重写则调用父类自身方法
- 子类重写了父类方法,则调用子类重写后的方法
!!!对象能调用的方法,主要看对象左边的引用类型!!!
package com.oop.Demo07;
//程序入口
public class Application07 {
public static void main(String[] args) {
//Student07能调用的类型只有自己独有的和继承自父类的
Student07 std1 = new Student07();
//父类的引用指向子类
//Person07 父亲类,可以指向子类但不能直接调用子类独有的方法(需要强转)
Person07 std2 = new Student07();
Object std3 = new Student07(); //Object是所有方法的父类
//对象能执行哪些方法,主要看对象左边的引用类型拥有哪些方法
//静态方法(无法重写)调用,优先调用自己引用类型内的方法
std2.say();
std1.say();
//子类没有重写的方法调用父类方法
std1.eat();
std2.eat();
//子类重写了的父类方法,则调用子类重写后的方法
std1.run();
std2.run();
//子类独有的方法只能子类调用
std1.walk();
((Student07)std2).walk(); //父类调用需要强转类型
}
}
///////////////////////////////////////////////////////////////
package com.oop.Demo07;
//父类
public class Person07 {
//父类的静态方法
public static void say(){
System.out.println("Person07说话!");
}
//子类有重写
public void run(){
System.out.println("Person07跑步!");
}
//子类没有重写
public void eat(){
System.out.println("Person07吃东西");
}
}
////////////////////////////////////////////////////////////////
package com.oop.Demo07;
//子类
public class Student07 extends Person07{
//自类的静态方法
public static void say(){
System.out.println("Student07说话!");
}
//继承方法重写
@Override
public void run() {
System.out.println("Student07跑步!");
}
//子类独有方法
public void walk(){
System.out.println("Student07散步!");
}
}
instanceof关键字
作用:
X instanceof Y 用来判断X类与Y类是否有继承关系,输出true/false
是否能编译通过取决于X的引用类型与Y是否有继承关系
是否输出true取决于X的实际类型是否是Y的子类型
类型转换
父类-------------->子类
高-------------------->低
高到低转换需要强转,父类要使用子类的方法需要强转
static
修饰方法,属性,被修饰的方法和属性随着类的加载同时被加载,且只执行一次
创建对象:静态(static)代码块>匿名代码块>构造方法
可修饰包
final
修饰引用、方法和类
被修饰的引用为常量
被修饰的方法无法被重写
被修饰的类无法被继承,为最终类,没有子类
abstract(抽象类)
修饰类和方法
修饰类(抽象类):
- 被修饰的类不能被实例化(即不能直接new 抽象类();),只能创建其子类对象
- 抽象类可以写普通方法,可以没有抽象方法
修饰方法(抽象方法):
- 抽象方法只有方法名,没有方法实现,例
public abstract void walk(); - 抽象方法必须必须在抽象类中
- 抽象方法必须在子类中被重写,除非子类也是抽象类
接口(interface)
interface修饰的类为接口- 接口中属性默认修饰符
public static final,所以只有常量 - 接口中方法默认修饰符
public abstrace - 接口中只能写抽象方法,不能写具体实现
- 不能直接实例化(不能直接new),要创建其接口实现类的对象,同抽象类
- 接口可以多继承,
implements来继承,","逗号隔开 - 其接口实现类(继承接口的类)必须实现方法
package com.oop.Demo09;
//程序入口
public class Application09 {
public static void main(String[] args) {
Student09 student09 = new Student09();
student09.say("Eleike");
}
}
/////////////////////////////////////////////////////////////////////////
package com.oop.Demo09;
//接口1
public interface Person09 {
//接口冲属性默认修饰符为public static final,所以接口中定义的属性都是常量
int age = 99;
//接口中方法默认修饰符是public abstrace
void say(String name); //其实为public abstrace void say(String name);
public abstract void eat();
void walk();
}
//////////////////////////////////////////////////////////////////////////
package com.oop.Demo09;
//接口2
public interface Father09 {
void run();
}
//////////////////////////////////////////////////////////////////////////
package com.oop.Demo09;
//接口实现类
public class Student09 implements Person09,Father09{ //implements继承
//必须要重写接口内所有方法
@Override
public void run() {
}
@Override
public void say(String name) {
System.out.println(name);
}
@Override
public void eat() {
}
@Override
public void walk() {
}
}
!!!类内调用子类方法实现创建并返回父类类型对象!!!
父类中设置静态方法,方法内调用子类(实现类)创建子类对象的方法来返回一个子类对象(可自动转化为父类类型对象),实现抽象类不必手动调用其实现类即可实例化(并非真的绕开了抽象类不能实例化的问题,只是方法内自动帮我们调用了其实现类)
像是日期类的java.util.Calendar,Calendar类中的Calendar.getInstance()方法就是此种用法
实例1:
package com.test.test03;
public class Application03 {
//程序入口
public static void main(String[] args) {
TestPerson03 tp1 = TestPerson03.getInstance(); //调用抽象方法内的实例化方法
System.out.println(tp1);
}
}
//////////////////////////////////////////////////////////////////////////////////////////////////
package com.test.test03;
//父类,抽象类,不可直接实例化
public abstract class TestPerson03 {
private String name;
private int age;
public abstract void say(); //抽象方法,无方法体
public abstract void walk(); //抽象方法,无方法体
//创建子类对象方法,返回值是TestPerson03类型
public static TestPerson03 getInstance(){
return TestSon03.createTestPeron03("Eleike",15); //调用子类中创建对象的方法
// return new TestSon03().createTestPeron03("eleike",88);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "TestPerson03{" +
"name='" + name + '\'' +
", a=" + age +
'}';
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////
package com.test.test03;
//子类,TestPerson03的实现类
public class TestSon03 extends TestPerson03{
@Override
public void say() {
}
@Override
public void walk() {
}
//创建自身对象的方法
public static TestPerson03 createTestPeron03(String name,int age){
TestSon03 ts1 = new TestSon03();
ts1.setAge(age);
ts1.setName(name);
return ts1; //返回一个自身类型对象
}
}
内部类
内部类
package com.oop.demo10;
//程序入口
public class Application10 {
public static void main(String[] args) {
Person10 per10 = new Person10();
//实例化内部类:通过这个外部类来实例化内部类
Person10.Inner in = per10.new Inner(); //实例化内部类
in.in();
}
}
//////////////////////////////////////////////////////////////////////////////////////////////
package com.oop.demo10;
public class Person10 {
private int age = 10;
public void out(){
System.out.println("这是外部类!");
}
//内部类,内部类可以访问外部类的私有属性
//加上static就是静态内部类
public class Inner{
public void in(){
System.out.println("这是内部类!");
System.out.println(age);
}
}
}
局部内部类
package com.oop.demo10;
public class Student10 {
public void eat(){
//局部内部类,写在方法内
class A{
public void say(){
System.out.println("局部内部类方法");
}
}
}
}
匿名内部类
匿名内部类,没有名字初始化类,不用将实例保存到变量中
package com.oop.demo10;
//一个java类文件中只能有一个public class,但可以有多个class
public class Application10 {
public static void main(String[] args) {
//匿名内部类,没有名字初始化类,不用将实例保存到变量中
new Sthool().teacher(); //直接使用方法
//匿名实例接口
User user = new User() {
@Override
public void name() {
}
};
}
}
class Sthool{
public void teacher(){
System.out.println("老师");
}
}
interface User{
void name();
}
异常
异常类分为两大类
Throwable(是所有类的超类,包含所有异常和错误):
- Error:错误
- Exception:异常
- IOException:检查性异常
- RuntimeException:运行时异常
范围:大————————————————————>小
Throwable—>Exception—>Error—>具体异常类
try/catch/finally
IDEA快捷键:Ctrl+Alt+t
finally可以跨过return和throw执行里面的代码
单个异常处理(单catch)
package com.exception;
//0不能为除数,会抛出一个ArithmeticException类异常
public class Demo01 {
public static void main(String[] args) {
int a = 1,b = 0;
try { //监控区域,监控可能出现的异常
System.out.println(a/b);
} catch (ArithmeticException e) { //catch(想要捕获的异常类型),捕获异常并做相应处理
//e.printStackTrace(); 打印错误的栈信息
System.out.println("0不能为除数");
} finally { //无论是否有异常,最终都会执行的代码块,通常用来善后工作
System.out.println("程序结束");
}
}
}
多个异常处理(多catch)
若要捕获多个异常:从小到大的去捕获
package com.exception;
public class Demo02 {
public static void main(String[] args) {
int a = 1,b = 0;
new Demo02().a();
//多个catch处理,catch中的异常类型要从小到大的去捕获
try {
new Demo02().a(); //匿名类直接调用方法
} catch (ArithmeticException e) {
System.out.println("ArithmeticException异常");
} catch (Error e1) {
System.out.println("Error异常");
}catch (Exception e2) {
System.out.println("Exception异常");
}catch (Throwable t) {
System.out.println("Throwable异常");
}finally {
System.out.println("异常处理结束");
}
}
//下面两个方法互相调用会出现堆栈溢出的错误(StackOverflowError)
public void a(){
b();
}
public void b(){
a();
}
}
!!try/catch总结!!
- try-catch放在循环里面是,如果出现异常,执行完异常再次执行语句时,若没有重新进行变量的定义,try语句仍然判断上一次的输入,即在此出现异常,如此往复,造成无限循环(所以创建Scanner要放在循环里面)。
- try-catch语句放在循环外面,出现异常会终止循环。
- finally一定会执行,可用来跳出循环。
实例1
package com.date;
import java.util.Scanner;
public class PrintCalendar {
public static void main(String[] args) {
while (true){
System.out.println("请输入数字:");
Scanner scanner = new Scanner(System.in); //放在循坏外就会无限循坏
try {
int number =scanner.nextInt(); //只接受int型
} catch (Exception e) {
System.out.println("输入异常,请重新输入:");
continue;
}
scanner.close(); //此条语句不能放在catch或finally语句中,否则也是无限循环
System.out.println(number); //输出输入内容
break;
}
}
}
throw
主动抛出异常,一般用在方法内,不常用
throw相当于return,使程序跳出当前方法,除非后面有finally代码块
package com.exception;
/**
* @author new wei
* @date 2021/12/2 23:33
*/
public class Demo03 {
public static void main(String[] args) {
try {
new Demo03().test03(1,0);
} catch (Exception e) {
System.out.println("异常处理了");
}
}
//假设这个方法中处理不了这个异常,主动抛出一个异常
public void test03(int a,int b){
if (b == 0){
//要具体
throw new ArithmeticException(); //throw主动抛出异常,一般在方法内使用
}
}
}
throws
方法主动抛出异常,一般用在方法上
package com.exception;
public class Demo04 {
public static void main(String[] args) {
try {
new Demo04().test04();
} catch (Exception e) {
System.out.println("捕获到异常");
}
}
//test04方法主动抛出一个Exception异常
public void test04() throws Exception{
throw new Exception();
}
}
自定义异常
创建自定义异常只需要创建一个类继承自Exception,类中描述内容,最终toString();输出错误描述信息
package com.exception;
public class Test01 {
public void say(int a) throws MyException{ //主动将方法中的异常向上抛出给调用者
if (a > 10){
//判读后主动抛出异常
throw new MyException(a); //用异常的有参构造器
}
}
//程序入口
public static void main(String[] args) {
try {
new Test01().say(11);
} catch (MyException e) {
System.out.println(e); //直接打印e相当于打印e.toString();
}
}
}
////////////////////////////////////////////////////////////////////////////////////////////
package com.exception;
//继承自Exception类
public class MyException extends Exception{
private int a;
//有参构造器,此类中没有无参构造器,所以无法使用无参构造
public MyException(int a) {
this.a = a;
}
@Override
public String toString() { //toString是默认返回创建者对该异常定义的错误描述
return "MyException{" + "a=" + a + '}';
}
}
杂记(常看)
-
除类名是首字母大写加驼峰规则,其他都是首字母小写加驼峰规则(常量全大写,字母下划线隔开)
-
除了八大基本类型其他都是引用类型,例:数组,string
-
BigDecimal 数学工具类,银行相关有业务,完善浮点数比较问题
-
Unicode编码表
-
拼接字符串"+":
- 前有String类型会变成拼接字符串:a=10,b=20,""+a+b=1020
- String类型放到后面正常计算:a=10,b=20,a+b+""=30
-
equals:判断字符串是否相等:
-
//equals只判断内容,不比较内存地址 "=="会判断两个对象在内存中的首地址,尽量不要用他判断字符串和对象 string s; s.equals("Hello") //判断字符串s是否等于Hello,
-
-
javac命令遇到错误: 编码GBK的不可映射字符问题:
-
javac -encoding utf-8 <文件名> #编码错误导致
-
-
在Java中能够影响到访问权限的只有private、public、protected(包括包访问权限)这几个关键字
-
修饰符范围:public>Protected>Default>private
-
一个java类文件中可以有多个class类,但是只能有一个public class类
-
System.exit(0);停止程序 -
构造方法不要加void修饰
-
throw和return同时出现会报错(Unreachable statement),但是finally可以让他们并存,最终finally里的内容覆盖前者,即使所描述内容不同
小问题
int a = 15中,变量名a是指向15的地址(或是15的Unicode代码位?或其他?),还是就是15这个值- 栈中的数据是共享的,所以编译器首先创建变量为a的引用,然后在栈中查找是否有15这个值,没有就将15存放到栈中并让a直接指向15;若栈中存在15,则让a直接指向15
- Integer自动拆包后赋值给int类型,然后两方用
==比较为什么结果为true?Integer类型不是对象吗?不应该是指向地址吗?- int类型和Integer对象用
==比较时Integer对象会自动拆箱,所以实际上比较的是Integer对象中int类型的成员常量value
- int类型和Integer对象用


浙公网安备 33010602011771号