静态与方法
调用静态和非静态方法:
调用非静态方法:也就是没有static修饰的方法体数据,需要进行【类 引用 = new 类名()】进行数据的实例化,然后通过【引用.方法名】进行调用。
调用静态方法:也就是有static修饰的方法体数据,直接通过【类名.方法名】调用
public class Customer {
// 姓名 :
String name;
// 无参构造方法
public Customer(){}
// 不带有static关键字的非静态方法
public void buyGoods(){
System.out.println(this.name+"在购物");
}
// 带有static关键字的静态方法
public static void toGoods(){
System.out.println(123456);
}
}
package textThis;
/**
* @author Monopkr
* @date 2022/5/14 - 9:10
*/
public class CustomerText {
public static void main(String[] args) {
// 调用非静态的方法
Customer c1 = new Customer();
c1.name = "张三";
System.out.println(c1.name);
c1.buyGoods(); // 可以对应修改到对应的name
Customer c2 = new Customer();
c2.name = "李四";
System.out.println(c2.name);
c2.buyGoods();
//调用static静态方法
Customer.toGoods();
}
}
综合:
package textThis;
/**
* @author Monopkr
* @date 2022/5/14 - 11:58
*/
public class CText {
public void doMethod1(){
System.out.println("这里是非静态的一级方法");
this.methods1(); // 调用二级非静态方法
CText.method2(); // 调用二级静态方法
}
public static void doMethod2(){
System.out.println("这里是静态的一级方法");
CText T1 = new CText(); // 调用二级非静态方法
T1.methods1();
CText.method2(); // 调用二级静态方法
}
public static void main(String[] args) {
CText T = new CText();
T.doMethod1();
System.out.println("--------------------");
CText.doMethod2();
}
public void methods1(){
System.out.println("二级非静态方法");
}
public static void method2(){
System.out.println("二级静态方法");
}
}
带有static的方法,其实既可以采用类名的方式访问,也可以采用引用的方式访问,但是即使采用引用的方式去访问,实际上执行的时候和引用指向的对象无关。不会出现空指针异常。
static的使用
静态变量:static修饰的变量: 如:static String country; 在类加载的时候初始化,不需要实例化对象,内存就开辟了。
静态代码块:
1、 语法格式: static{
java语句;
}
2、静态代码块在类加载时执行,并且只执行一次。
3、静态代码块在一个类中可以编写多个,并且遵循自上而下的顺序依次执行。
4、静态代码块的作用:
public class staticText{
static{
System.out.println("类加载");
}
public static void main (String[] args){
System.out.println();
}
}
实例代码块:
public class staticText{
// 实例代码块
{
System.out.println("类加载");
}
public static void main (String[] args){
System.out.println();
}
}
静态方法:
方法什么时候定义为静态:方法描述的是动作,当所有的对象执行这个动作的时候,最终产生的影响都是一样的,那么这个动作已经不再属于某个对象的动作了,可以将这个动作提升为类级别的动作,模板级别的动作
静态方法中无法直接访问 【实例变量】 和 【实例方法】,需要通过实例化对象/类
对象和类:
实例变量:定义前无static ;如:private String name; name即是实例变量、也是对象变量
静态变量:前面有static修饰,
对于方法的封装:有static修饰的方法,通过 类名.方法名(实参) 无需实例化
无static修饰的方法,通过 引用.方法名(实参) 需先实例化得到引用,为实例方法,实例方法调用时一定要有对象的存在
构造方法:
// 构造方法的类
public class User {
String name;
int age;
// 构造方法:语法结构:
/*
* [修饰符] 构造方法名称(形象){
* 构造方法体;
* }
* 构造方法注意点: ①构造方法需要与当前类名一致
* ②不需要制定返回值类型
* ③也不能写 void
*
* 作用:通过构造方法得调用,创建对象;
* 调用:在外部类中 通过“ new 构造方法名称(实参) ” 调用
* 返回的是就是构造方法内容
* */
public User(){
System.out.println("无参数的构造方法");
}
public User(int i){
System.out.println("有参数的构造方法");
}
}
// 调用构造方法的类
// 语法: new 构造方法名称(实参)
public class text1 {
public static void main(String[] args) {
User user1 = new User(); //调用构造方法
User user2 = new User(10);//调用有参数的构造方法
}
}
参数的传递:
方法的调用的时候,涉及到参数传递的问题,传递的时候,Java只遵循一种语法机制,就是将变量中保存的“值“ 传递过去,只不过有的时候这个值是一个字面值,有的时候这个值是一个Java对象的内存地址。
this 关键字的使用
this 是一个关键字,是一个引用,是一个变量,this变量中保存了内地址指向了自身,this 存储在jvm堆内存Java对象内部。指向当前的对象
- this 可以出现在”实例化方法“当中,this 指向当前正在执行这个动作的对象。(this代表当前对象)
- this 在多数情况下都是可以省略不写的,但是在区分局部变量和实例变量的时候不亏省略(如:get和set的时候)。
- this 不能使用在带有static 的方法当中,因为带static的 方法,不需要对象,直接使用类名;所以执行过程中没有当前对象,所以不能使用this
继承:
public class ExtendsText {
public static void main(String[] args) {
/** 继承的基本作用 代码的复用。但是继承最重要的作用是 有了继承才有后面的“方法的覆盖”和“多态机制”
* 继承的语法格式:
* [修饰符例表] class 类名 extends 父类名{
* 类体 = 属性 + 方法
* }
* java中的继承是单继承,一个类只能继承一个类,但是可以间接继承其他类
*
* ① 私有的不支持继承
* ② 构造方法不支持继承
* ③ 其他数据都可以继承
*/
ParentClass p = new ParentClass();
p.setName("彭科瑞");
System.out.println(p.getName());
}
}
方法的重写/覆盖:
* 【方法的重载】:在同一个类的中,方法完成的功能是相似的; * 条件:同一个类中,方法名相同,参数列表不同(类型、顺序、个数) * * 【方法的覆盖】(方法的重写)override 方法的重写发生在具有继承关系的父子类之间。 * 什么时候使用方法重写: 当当前的父类中的方法已经无法满足当前子类的业务需求, * 子类要将父类中继承的方法进行重新的编写 * 【返回值类型相同,方法名相同,形参列表相同】 访问权限不能更低,可以更高, 抛出异常不能更多,可以更少私有方法不能继承,所以不能覆盖。
构造方法不能继承,所以不能覆盖。
静态方法不存在覆盖。
覆盖只针对方法,不谈属性。
多态
关于java语言种的多态语法机制 1、 Animal、Cat、Dog 三个类之间的关系: Cat 继承 Animal Dog 继承 Animal 2、多态: ① 向上转型:子类型 转化为 父类型 (自动类型转换) ② 向上转型父类型 转化为 子类型 (强制转换类型) 向上转型和向上转型,父子两种类型之间必须必须要有继承关系 多态语法机制 new Cat() 创建的对象的类型是Cat a2这个引用数据类型是Animal,可见进行了类型转换 java 允许 父类型引用 指向 子类型对象 编译时:看左侧的类型, 运行时:看右侧的类型 Animal a2 = new Cat(); a2.move();总结:父类型引用指向子类型对象这种机制导致程序在编译阶段绑定和运行阶段绑定两种不同的形态 / 状态。这种机制可以成为一种多态语法机制。
通过多态访问子类型特有的方法:【向下转型】
强制类型转换: 父 a1 = new 子(); 子 b1 = (子) a1 ;
避险:避免在向下转型的时候出现classCastException。
使用instanceof运算符可以避免出现以上的异常。
instanceof 运算符怎么用:
格式语法: (引用 instanceof 数据类型名)
以上运算符的执行结果类型是布尔型,结果可能是true / false。
判断引用是否和数据类型一致
Animal a3 = new Dog(); // Cat c3 = (Cat) a3; // 实际上 是Dog存在实例对象,Dog 与 Cat 之间没有关系 if(a3 instanceof Cat){ // 当 c3 类型确实是 Cat 的时候 在进行转换 Cat c3 = (Cat) a3; c3.catChMouse(); }else if (a3 instanceof Dog){ // 当 c3 类型确实是 Dog 的时候 在进行转换 Dog d3 = (Dog) a3; d3.eat(); }
final 关键字:
修饰方法:表明该方法是最终方法,不能被重写
修饰变量:表明该变量是常量,不能被再次赋值
修饰类:表明该类是最终类,不能被继承变量是基本数据类型时
final修饰 指的是基本数据类型的数据值不能发生改变
变量是引用数据类型时
final修饰 指的时引用数据类型的地址值不能发生改变,但是地址里面的内容可以改变final 修饰成员变量 初始化时机
在创建的时候,直接给值
在构造方法结束之前,完成赋值
一般情况先手动赋值;
final修饰的实例变量是不可变的,这种一般和static联合使用,“常量”
常用定义语法格式:
public static final 类型 常量名 = 值
数组:
数组的声明定义:
语法:给长度不加{},给{}不加长度
// 动态:数组的初始化和数组元素的赋值操作分开进行
类型 [] 参数 = new 类型[长度];
类型 参数[] = new 类型 [长度];
// 静态:数组的初始化和数组元素的赋值操作同时进行
类型 [] 参数 = new 类型 [] {内容}
String [] name = new String [] {"张三","李四"}
// 输出数组
/ 使用 Arrays.toString(参数) 一维数组 // Arrays.deepToString(参数) 二维数组
System.out.println(Arrays.toString(name));
内部类:
静态内部类 只能访问 外部类的静态属性------直接【外部类.属性】
非静态内部类可以访问 外部静态 / 非静态属性-----静态属性【外部类.属性】,非静态【外部类.this.属性】
abstract抽象类:
abstract 修饰的结构是 类、方法(不确定的、泛指对象)
abstract 修饰类:抽象类:(public)abstract class 类名{}
- 抽象类不能被实例化。也就是不能直接new一个抽象类,只能由它的继承类实例化。
- 抽象类一定有构造器,便于子类实例化时调用(涉及:子类对象实例化的全过程)。
- 开发中,都会提供抽象类的子类,让子类对象实例化,完成相关的操作。
- 抽象类不能使用final关键字修饰,因为final修饰的类是无法被继承,而对于抽象类来说就是 需要通过继承去实现抽象方法,这又会产生矛盾。
abstract 修饰方法:抽象方法:
- 抽象方法只有方法的声明,没有方法体。也就是 public abstract void 方法();
- 包含抽象方法的类,一定是一个抽象类。反之,抽象类中可以没有抽象方法。(抽象类中可以没抽象方法,有抽象方法的类一定是抽象类)。
- 抽象方法不能用private修饰,因为抽象方法必须被子类实现(覆写),而private权限对于子类来 说是不能访问的,所以就会产生矛盾。
- 若子类重写了父类所有的抽象方法后,此子类方可实例化(不需要是抽象类)。若子类没有重写父类中的所有的抽象方法,则此子类也是一个抽象类,需要使用abstract修饰。 要么重写父类中所有的抽象方法,要么不全部重写是抽象类(不推荐)。
接口:
接口概念:
一个接口只有方法的特征没有方法的实现,因此这些方法可以在不同的地方被不同的类实现,而这些实现可以具有不同的行为(功能)。
里面全部是由全局常量和公共的抽象方法所组成。
接口的特点:
一个接口也能够拥有方法和属性,但是在接口中声明的方法默认是抽象的。(即只有方法标识符,而没有方法体)。
接口中存在的变量一定是final,public,static的。
具体的方法体的实现是由继承该接口的类来的实现的。接口并不用管具体的实现。
实现接口:在实现类中通过 implements 来实现接口;
Calender类
Calendar是抽象类,创建实例时不能用new,而是使用Calendar.getInstance();
异常处理:
编译时异常:
使用try-catch-finally处理编译时异常,是得程序在编译时就不再报错,都是在运行时仍可能报错。
相当于我们使用 try-catch-finally 将一个编译时可能出现的异常,延迟到运行时出现。
运行时异常:
package day_16_throw;
import java.util.Date;
import java.util.Scanner;
/**
* @author Monopkr
* @date 2022/5/20 - 16:29
* 1、因为编程错误或者偶然的外在因素导致的一般性问题,可以使用针对性的代码处理
*/
public class ExceptionTest {
public static void main(String[] args) {
ExceptionTest e = new ExceptionTest();
e.test6();
}
// 1、数组越界 ArrayIndexOutOfBoundsException
// 指使用非法索引访问数组。索引为负值或大于或等于数组的大小
public void test2(){
String str= "PKR";
System.out.println(str.charAt(3));
}
// 2、空指针异常,NullPointerException
public void test1(){
String str = null;
System.out.println(str.charAt(1));
}
// 3、 类型转换异常 ClassCastException
public void test3(){
Object obj = new Date();
String str = (String)obj; // 强制转换 为 obj 类型
}
// 4、数字类型的转换 NumberFormatException
public void test4(){
// String str = "123"; // 成功
String str = "abc"; // 失败:不是数字类型转数字类型
Integer.parseInt(str);
}
// 5、输入不匹配: InputMismatchException
public void test5(){
Scanner scanner = new Scanner(System.in);
int score = scanner.nextInt(); // 目前需输入的为数字型
System.out.println(score);
}
// 6、算数异常: ArithmeticException
public void test6(){
int a = 10;
int b = 0; // 计算异常
System.out.println(a / b);
}
}
线程:
何时需要使用多线程:
- 程序需要同时执行两个或者多个任务的时候。
- 程序需要实现一些需要等待的任务时,如用户输入、文件的读写、操作、网络操作、搜索等。
- 需要一些后台运行的程序时。