一、方法重载 VS重写
方法重载:方法名称相同,但参数的类型或参数的个数不同。
方法重写:方法名称、参数类型和返回值类型全部相同。
二、java的三大特性
1、封装:
2、继承:
3、多态:允许程序中出现重名现象,分为方法重载和对象多态
方法重载:在一个类中,允许多个方法使用同一个名字,但方法的参数个数或类型不同,完成的功能不同
对象多态:子类对象可以与父类对象进行相互交换,而且根据其使用的子类的不同,完成的功能也不同
三、字符串常用方法
四、this、super关键字
this关键字表示内容:
1)表示类中的属性
2)使用this调用本类的构造方法(注意:使用this构造方法必须也只能放在构造方法的第1行,同时this调用构造方法时,程序中至少存在一个构造方法不调用this调用其他构造方法)
3)this表示当前对象
五、关键字static、final
static作用:被所有对象共享
1、注意:非static声明的方法可以去调用static声明的属性或方法。static声明的方法不能调用非static类型声明的属性或方法
final关键字:
1、使用final声明的类不能有子类
2、final声明的方法不能被子类重写
3、final声明的变量即成为常量,常量不可以修改
六、java内存区域
在java中主要存在4块内存空间,主要如下:
1)栈内存:保存所有的对象名称
2)堆内存:保存每个对象的具体属性
3)全局数据区:保存static类型的属性
4)全局代码区:保存所有的方法定义
七、代码块
代码块分为:普通代码块、构造块、静态代码块(使用static 关键字声明的代码块)、同步代码块
执行顺序:静态代码块 》构造块 》构造方法,同时,静态代码块只执行1次,每次实例化对象时都会执行构造块中的代码,会执行多次
class Demo{
{
System.out.println("1、构造块");
}
public Demo() {
System.out.println("2、构造方法");
}
static {
System.out.println("0、静态代码块");
}
}
public class javaDemo {
public static void main(String args[]) {
new Demo(); //实例化对象
new Demo();
new Demo();
}
}
运行结果:
0、静态代码块
1、构造块
2、构造方法
1、构造块
2、构造方法
1、构造块
2、构造方法
八、继承
1、使用关键字 extends进行继承,只允许多层继承,不允许多重继承,即一个子类只能继承一个父类,一个父类还可以有一个父类。
2、子类不能直接访问父类中的私有成员,可以调用父类的非私有方法
3、子类的实例化
1)先调用父类构造
2)再调用子类构造
实例化子对象顺序:先子类的静态代码块 》 父类的构造块 》 父类构造方法 》子类构造块 》子类构造方法,其中静态代码块只出现1次
示例:
class Person{
{
System.out.println("1、构造块");
}
public Person() {
System.out.println("2、构造方法");
}
static {
System.out.println("0、静态代码块");
}
}
class Student extends Person{
{
System.out.println("Student 构造块");
}
public Student(){
System.out.println("Student 构造方法");
}
static {
System.out.println("Student 静态代码块");
}
}
public class javaDemo {
public static void main(String args[]) {
new Person(); //实例化对象
new Person(); //实例化对象
new Person(); //实例化对象
new Student(); //实例化子对象:先静态代码块(父类、子类) 》 父类的构造块 》 父类构造方法 》子类构造块 》子类构造方法,其中静态代码块只出现1次,由于在newPerson已出现1次,所以子类时不出现父类的静态代码
new Student();
}
}
运行结果如下:
九、抽象类
作用:类似“模板”,其目的是要设计者依据它的格式来修改并创建新的类,但是并不能直接由抽象类创建对象,只能通过抽象类派生出新的类,再由它来创建对象,只能单继承
定义及使用规则:
1)包含一个抽象方法的类必须是抽象类
2)抽象类和抽象方法都要使用abstract关键字声明
3)抽象方法只需声明而不需要实现
4)抽象类必须被子继承,子类(如果不是抽象类)必须覆写抽象类中的全部抽象方法
注意:抽象类的对象不能直接实例化,其他和普通类一样
abstract class Person { //定义抽象类
private String name;
private String age;
public Person(String name,String age){
this.name = name;
this.age = age;
}
public void getPerson(){
System.out.println("姓名:"+name+",年龄:"+age);
}
public abstract void getInfo(); //定义抽象方法
}
class Student extends Person{
private String school;
public Student(String name,String age,String school){
super(name,age);
this.school = school;
}
public void getInfo(){ //重写抽象方法
System.out.println("Student getInfo,school为:"+school);
}
}
public class testPerson{
public static void main(String[] args){
//Person te = new Person( "张三", "25"); //抽象类不能实例化
//te.getPerson();
Student st = new Student("学生","12","深圳一小");
st.getInfo();
}
}
十、接口
接口interface是一种特殊的类,是由全局常量和公共的抽象方法所组成,主要用于制定标准
格式:
interface 接口名称{
全局常量;
抽象方法;
}
使用:
1、一个子类允许同时实现多个接口
2、搭配抽象类使用,方式是:class A extends 抽象类B implements 接口C,接口D
示例
interface A{
public String AUTHOR = "TOM"; //定义全局常量
public void printA(); //定义抽象方法
}
interface B{
public void printB(); //定义抽象方法
}
interface C extends A,B{ //定义接口C,同时继承接口A,B
public void printC();
}
abstract class Food{
private String name;
private String color;
public Food(String name,String color) { //定义构造方法
this.name = name;
this.color = color;
}
public abstract void getInfo(); //定义抽象方法
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
}
class Fruit extends Food implements C{ //继承抽象类,实现接口
private String address;
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public Fruit(String name,String color,String address) {
super(name,color);
this.address = address;
}
public void getInfo() {
System.out.println("产品:"+this.getName()+",颜色为:"+this.getColor()+",产地为:"+this.address);
}
public void printA() {
System.out.println("方法printA,内容为:"+AUTHOR); //需重写接口A方法
}
public void printB() { //需重写接口B方法
System.out.println("方法printB");
}
public void printC() {
System.out.println("方法printC");
}
}
public class InterfaceDemo{
public static void main(String args[]) {
Fruit ft = new Fruit("苹果","红色","陕西");
ft.getInfo(); //输出:产品:苹果,颜色为:红色,产地为:陕西
ft.printA(); //输出:方法printA,内容为:TOM
ft.printB(); //输出:方法printB
ft.printC(); //输出:方法printC
}
}
接口和对象的区别
十一、对象多态
对象多态,分为:
1)向上转型:子类对象 -》父类对象
2)向下转型: 父类对象 -》子类对象
对象转型格式:
对象向上型: 父类 父类对象 = 子类实例;
对象向下型:子类 子类对象 = (子类)父类
注意:
1)在发生向下转型前,必须先发生向上转型,否则将出现对象转换异常。
2)一旦发生对象的向上转型关系后,调用的方法一定是被子类重写过的方法
示例:
class Person{
{
System.out.println("1、构造块");
}
public Person() {
System.out.println("2、构造方法");
}
static {
System.out.println("0、静态代码块");
}
public void fun1() {
System.out.println("Person --> fun1");
}
public void fun2() {
System.out.println("Person --> fun2");
}
}
class Student extends Person{
{
System.out.println("Student 构造块");
}
public Student(){
System.out.println("Student 构造方法");
}
static {
System.out.println("Student 静态代码块");
}
public void fun1() {
System.out.println("Student --> fun1");
}
public void fun3() {
System.out.println("Student --> fun3");
}
}
public class javaDemo {
public static void main(String args[]) {
Student st = new Student(); //实例化对象:静态代码块(父类、子类)-》父类构造(构造块、构造方法)-》子类构造(构造块、构造方法)
Person p = st; //发生了向上转型
p.fun1(); //调用了子类的重写方法:Student --> fun1
Person p1 = new Person();
Student st1 = (Student) p1; //向下转型前,没有发生向上转型,报错类型转换失败
st1.fun1();
st1.fun2();
st1.fun3();
}
}
运行结果:
十二、异常的捕获及其处理
异常捕获作用:如果不对程序的异常进行处理,程序出现异常就中断,无法执行后续语句,捕获了对应的异常,可以执行后续语句。
异常的最大父类是Throwable,其分为两个子类:Exception和Error,Exception为程序处理的异常,而Error表示JVM错误,一般不由程序处理。
格式:
异常的处理流程
注意点:
1)有多个异常时,捕获范围小的异常必须放在捕获大的异常之前,否则编译时就会出现错误提示
2)如果有多个异常最好分别进行捕获,而不要直接使用Exception捕获全部异常
示例:
public class ExceptionDemo {
public static void main(String args[]) {
try {
int temp = 10 / 0;
System.out.println("两个数字相除结果:"+temp); //此代码不再执行
}catch(ArithmeticException e) {
System.out.println("算术异常:"+e);
}finally {
System.out.println("执行finally内容");
}
System.out.println("*****计算结束****");
}
}
运行结果:
关键字throws
在定义一个方法时使用throws关键字声明,表示该方法不处理异常,而交给方法的调用处处理异常。
格式:
public 返回值类型 方法名称(参数列表)throws 异常类{}
示例:
class Math{
public int div(int i,int j)throws Exception{
int temp = i /j ;
return temp;
}
}
public class ExceptionDemo {
public static void main(String args[]) {
Math m = new Math();
try {
System.out.println("两个数字相除结果:"+m.div(10, 0));
}catch(ArithmeticException e) {
System.out.println("ArithmeticException e");
e.printStackTrace();
}catch(Exception e){
System.out.println("exception e");
e.printStackTrace();
}finally {
System.out.println("执行finally内容");
}
System.out.println("*****计算结束****");
}
}
关键字 throw
使用throw 抛出一个异常,抛出时直接抛出异常类的实例
Exception 和RuntimeExcption的区别
1)Exception在程序中必须使用try … catch进行处理
2)RuntimeException可以不使用try …catch进行处理,但是如果有异常产生,则异常将由JVM进行处理。注意对于RuntimeException的子类最好也使用异常处理机制,否则一旦出现异常,还是会导致程序中断执行
十三、包
1、访问权限
2、命名规范
1)类:所有单词的首字母大写,如TestJava
2)方法:第一个单词的首字母小写,之后每个单词的首字母大写,如getInfo()
3)属性:第一个单词的首字母小写,之后每个单词的首字母大写,如studentName
4)包:所有单词的字母小写,如org.lxh.demo
5)常量:所有单词的字母大写,如FLAG
十四、多线程
实现多线程的方式:
1)继承Thread类
2)实现Runnable接口 (推荐使用该方式)
示例:
class MyThread extends Thread{ //继承Thread类
private int ticket =5; //一共5张票
public void run() { //覆写run()方法
for(int i =0;i<100;i++) { //超出票数的循环
if(ticket >0) { //判断是否有剩余票
System.out.println(Thread.currentThread().getName()+",卖票Thread:ticket ="+ticket --);
}
}
}
}
class MyThread1 implements Runnable{ //实现Runnable方法
private int ticket =5; //一共5张票
public void run() { //覆写run()方法
for(int i =0;i<100;i++) { //超出票数的循环
if(ticket >0) { //判断是否有剩余票
System.out.println(Thread.currentThread().getName()+"卖票Runnable:ticket ="+ticket --);
}
}
}
}
public class threadDemo {
public static void main(String args[]) {
MyThread m1 = new MyThread(); //定义线程对象
MyThread m2 = new MyThread(); //定义线程对象
m1.start(); //启动第1个线程
m2.start(); //启动第2个线程
System.out.println("---Runnable---");
MyThread1 rm1 = new MyThread1();
Thread t1 = new Thread(rm1); //启动第1个线程
Thread t2 = new Thread(rm1); //启动第2个线程
t1.start();
t2.start();
}
}
其中一种运行结果:
注意点:
1、继承thread类,启动多个线程,每个线程都卖出了5张票,实现Runnable接口,启动多个线程,一共被卖出了5张票,也就是ticket属性被所有线程对象共享。
可见,实现Runnable接口相对于继承Thread类来说,有如下显著的优势:
1)适合多个相同程序代码的线程去处理同一资源的情况
2)可以避免由于java的单继承性带来的局限
3)增强了程序的健壮性,代码可以被多个线程共享,代码和数据是独立的。
2、java程序每次运行至少启动2个线程:一个是main线程,一个是垃圾收集线程
3、主方法实际上也是一个线程,同时要注意的是,在java中所有的线程都是同时启动的,哪个线程先抢占到了CPU资源,哪个就先运行。由于线程的不确定性,所以主线程有可能最先执行完,那么此时其他线程不会受到任何影响,并不会随着主线程的结束而结束
线程的状态:
1、创建状态
程序中用构造方法创建了一个线程对象后,新的线程对象便处于新建状态,此时,它已经有了相应的内存空间和其他资源,但还处于不可运行状态。如:Thread t = new Thread();
2、就绪状态:
新建线程对象后,调用该线程的start()方法就可以启动线程。当线程启动时,进入就绪状态,线程将进入线程队列排队,等待CPU服务
3、运行状态
当就绪状态的线程被调用并获得处理器资源时,线程就进入了运行态,此时,自动调用该线程对象的run()方法
4、堵塞状态
一个正在执行的线程在某些特殊情况下,如被人为挂起或需要执行耗时的输入/输出操作时,将让出CPU并暂时中止自己的执行,进入堵塞状态。在可执行状态下,如果调用sleep()、suspend()、wait()等方法,线程都将进入堵塞状态。
5、死亡状态
线程调用stop()方法或run()执行结束后,即处于死亡状态
class MyThread1 implements Runnable{ //实现Runnable方法
private int ticket =5; //一共5张票
public void run() { //覆写run()方法
for(int i =0;i<100;i++) { //超出票数的循环
if(ticket >0) { //判断是否有剩余票
System.out.println(Thread.currentThread().getName()+"卖票Runnable:ticket ="+ticket --);
}
}
}
}
public class threadDemo {
public static void main(String args[]) {
MyThread1 rm1 = new MyThread1();
Thread t1 = new Thread(rm1);
System.out.println("线程开始执行之前 --》"+t1.isAlive()); //输出false
t1.start(); //启动线程
System.out.println("线程开始执行之后 --》"+t1.isAlive()); //输出true
for (int i = 0;i<3;i++) {
System.out.println("main 运行 --》"+i);
}
System.out.println("代码执行之后 --》"+t1.isAlive()); //输出结果不确定
}
}
运行结果(其中1种):
以上输出结果是不确定的,有可能到最后线程已经不存活了,但也有可能继续存活,这就看哪个线程先执行完。主线程有可能比其他线程先执行完
线程的主要方法
判断线程是否启动:isAlive()
线程的强制执行:join
可以使用join()方法让一个线程强制运行,线程强制运行期间,其他线程无法运行,必须等待此线程完成之后才可以继续执行。
示例:
class MyThread1 implements Runnable{ //实现Runnable方法
private int ticket =5; //一共5张票
public void run() { //覆写run()方法
for(int i =0;i<100;i++) { //超出票数的循环
if(ticket >0) { //判断是否有剩余票
System.out.println(Thread.currentThread().getName()+"卖票Runnable:ticket ="+ticket --);
}
}
}
}
public class threadDemo {
public static void main(String args[]) {
MyThread1 rm1 = new MyThread1();
Thread t1 = new Thread(rm1,"线程A");
System.out.println("线程开始执行之前 --》"+t1.isAlive()); //输出false
t1.start(); //启动线程
System.out.println("线程开始执行之后 --》"+t1.isAlive()); //输出true
for (int i = 0;i<15;i++) {
if(i >10) {
try {
t1.join(); //线程t1进行强制运行
}catch(Exception e) {
e.printStackTrace();
}
}
System.out.println("main 运行 --》"+i);
}
System.out.println("代码执行之后 --》"+t1.isAlive()); //输出结果不确定
}
}
运行结果:
线程开始执行之前 --》false
线程开始执行之后 --》true
main 运行 --》0
main 运行 --》1
main 运行 --》2
main 运行 --》3
线程A卖票Runnable:ticket =5
main 运行 --》4
main 运行 --》5
main 运行 --》6
main 运行 --》7
main 运行 --》8
main 运行 --》9
main 运行 --》10
线程A卖票Runnable:ticket =4
线程A卖票Runnable:ticket =3
线程A卖票Runnable:ticket =2
线程A卖票Runnable:ticket =1
main 运行 --》11
main 运行 --》12
main 运行 --》13
main 运行 --》14
代码执行之后 --》false
十五、泛型
1、泛型的作用:解决数据类型的安全性问题,主要原理是在类声明时通过一个标识表示类中某个属性的类型或者某个方法的返回值及参数类型。
2、泛型类定义
[访问权限] class 类名称<泛型类型标识1,泛型类型标识2,…,泛型类型标识3>{
[访问权限] 泛型类型标识 变量名称;
[访问权限] 泛型类型标识 方法名称() {};
[访问权限] 返回值类型声明 方法名称(泛型类型标识 变量名称) {};
}
实例化:
类名称<具体类> 对象名称 = new 类名称<具体类>();
3、注意点:
1)在泛型的指定中是无法指定基本数据类型的,必须设置成一个类
2)一个类的子类可以通过对象多态性为其父类实例化,但是在泛型操作中,子类的泛型类型是无法使用父类的泛型类型接收的
示例
class Info<T,V>{ //指定两个泛型类型
private T var; //第1个泛型属性
private V value; //第2个泛型属性
public V getValue() {
return value;
}
public void setValue(V value) {
this.value = value;
}
public Info(){
}
public Info(T var,V value){ //通过构造方法设置
this.setVar(var);
this.setValue(value);
}
public T getVar() {
return var;
}
public void setVar(T var) {
this.var = var;
}
}
public class GenericsDemo {
public static void main(String args[]){
Info<String,Integer> p = new Info<String,Integer>();
p.setValue(16);
p.setVar("张三");
System.out.println("信息Info为:"+p.getVar()+","+p.getValue());
fun(p);
}
public static void fun(Info<?,?> temp){ //对象引用,使用?匹配任意类型
System.out.println("fun信息Info为:"+temp.getVar());
}
}
运行结果:
十六、Java常用类库
1、StringBuffer类
如果一个字符串要被经常改变,必须使用StringBuffer类。与String比较,StringBuffer的内容是可以进行修改的。String的内容一旦声明则不可改变,如果要改变,则改变的是String的引用地址
示例:
public class StringBufferDemo {
public static void main(String args[]){
StringBuffer bf = new StringBuffer();
StringBuffer bf1 = new StringBuffer();
bf1.append("新时代");
bf.append("hello");
bf.append(bf1); //追加内容,可以追加数据类型:char/String/StringBuffer
bf.insert(0, "heyhey!"); //在指定位置插入指定字符串
System.out.println(bf);
System.out.println(bf.indexOf("冬至")); // 查找指定字符串是否存在,若不存在返回-1
System.out.println(bf.indexOf("春节"));
System.out.println(bf.reverse()); //将内容反转保存
System.out.println(bf.length()); //求出内容长度
System.out.println(bf.delete(0, 3)); //删除指定范围的字符串
System.out.println(bf.substring(0, 3)); //字符串截取
System.out.println(bf.replace(0, 5, "123")); //指定位置内容替换
}
}
运行结果:
2、Runtime类
Runtime类表示运行时操作的类,是一个封装了JVM进程的类,其构造方法是私有化的(单例设计),要取得一个Runtime实例,方式如下:
Runtime run = Runtime.getRuntime();
示例:
public class RuntimeDemo {
public static void main(String args[]){
Runtime rt = Runtime.getRuntime(); //取得Runtime类实例
System.out.println(rt.maxMemory()); //返回JVM的最大内存量
System.out.println("调用前:"+rt.freeMemory()); //调用前返回Java虚拟机的空闲内存量
String str ="hello";
for(int i =0;i<1000;i++){
str +=i;
}
System.out.println("调用后:"+rt.freeMemory()); //返回Java虚拟机的空闲内存量
rt.gc(); //运行垃圾回收器,释放空间
System.out.println("垃圾回收后"+rt.freeMemory());
}
}
结果:
3、System类
常用方法示例:
class Person1{
private String name;
private String age;
public Person1(String name,String age){
this.name = name;
this.age = age;
}
public void getPerson(){
System.out.println("姓名:"+name+",年龄:"+age);
}
public String getInfo(){
return "姓名"+this.name;
}
public void finalize() throws Throwable{ //对象释放空间时默认调用此方法
System.out.println("对象被释放 --》"+this.getInfo());
}
}
public class SystemDemo {
public static void main(String args[]){
System.out.println("毫秒数"+System.currentTimeMillis()); //获取系统当前毫秒数
System.getProperties().list(System.out);; //获取系统配置
System.out.println("系统编码方式:"+System.getProperty("file.encoding")); //获取单个系统属性
Person1 p = new Person1("张三","16");
p = null; //断开引用,方便回收
System.gc(); //强制性释放空间
}
}
运行结果:
毫秒数1640136100215
– listing properties –
java.runtime.name=Java™ SE Runtime Environment
sun.boot.library.path=D:\Program Files\JDK\anzhuang\jre\bin
java.vm.version=25.131-b11
java.vm.vendor=Oracle Corporation
maven.multiModuleProjectDirectory=$MAVEN_HOME
java.vendor.url=http://java.oracle.com/
path.separator=;
java.vm.name=Java HotSpot™ 64-Bit Server VM
file.encoding.pkg=sun.io
user.script=
user.country=CN
sun.java.launcher=SUN_STANDARD
sun.os.patch.level=
java.vm.specification.name=Java Virtual Machine Specification
user.dir=E:\workspace\testDemo
java.runtime.version=1.8.0_131-b11
java.awt.graphicsenv=sun.awt.Win32GraphicsEnvironment
java.endorsed.dirs=D:\Program Files\JDK\anzhuang\jre\lib…
os.arch=amd64
java.io.tmpdir=C:\Users\DENGDA~1\AppData\Local\Temp\2
line.separator=
java.vm.specification.vendor=Oracle Corporation
user.variant=
os.name=Windows 10
sun.jnu.encoding=GBK
java.library.path=D:\Program Files\JDK\anzhuang\bin;C:…
java.specification.name=Java Platform API Specification
java.class.version=52.0
sun.management.compiler=HotSpot 64-Bit Tiered Compilers
os.version=10.0
user.home=C:\Users\dengdanchan
user.timezone=
java.awt.printerjob=sun.awt.windows.WPrinterJob
file.encoding=GBK
java.specification.version=1.8
user.name=dengdanchan
java.class.path=E:\workspace\testDemo\bin
java.vm.specification.version=1.8
sun.arch.data.model=64
java.home=D:\Program Files\JDK\anzhuang\jre
sun.java.command=testDemo.SystemDemo
java.specification.vendor=Oracle Corporation
user.language=zh
awt.toolkit=sun.awt.windows.WToolkit
java.vm.info=mixed mode
java.version=1.8.0_131
java.ext.dirs=D:\Program Files\JDK\anzhuang\jre\lib…
sun.boot.class.path=D:\Program Files\JDK\anzhuang\jre\lib…
java.vendor=Oracle Corporation
file.separator=
java.vendor.url.bug=http://bugreport.sun.com/bugreport/
sun.cpu.endian=little
sun.io.unicode.encoding=UnicodeLittle
sun.desktop=windows
sun.cpu.isalist=amd64
系统编码方式:GBK
对象被释放 --》姓名张三
4、正则表达式
依赖于Pattern类和Matcher类,Pattern类主要是进行正则规范的编写,Matcher类主要是执行规范
示例:
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class RegrexDemo {
public static void main(String args[]){
String date1 = "2021-12-01";
String patter1 = "\\d{4}-\\d{2}-\\d{2}";
Pattern p = Pattern.compile(patter1);
Matcher m = p.matcher(date1);
if(m.matches()){
System.out.println("日期格式合法");
}else{
System.out.println("日期格式不合法");
}
}
}
十六、写法易错点
1、进行相等比较时,建议使用以下方式:“固定字符串”.equals(“输入字符串”),这样可以避免空指针问题
public class Demo{
public static void main(String args[]) {
String str = null;
System.out.println("csdn".equals(str)); //建议使用这种方式
System.out.println(str.equals("csdn")); //不建议:容易出现空指针问题
}