携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第26天,点击查看活动详情
三大特征
封装、继承、多态
方法的调用
静态方法、非静态方法
静态方法可以调用静态方法,非静态调用非静态,但不能混合调用
例:可以如下静态方法间调用
public static void a(){
b();
}
public static void b(){
}
但不可以静态与非静态混合调用
public void a(){
b();
}
public static void b(){
}
形参和实参
实参
add(1,2);
形参
add(int a,int b){
return a+b;}
值传递和引用传递(oop.demo1.Test1-Test3)
值传递
Test1
传递对象的一个副本,即使副本被改变,也不会影响源对象,因为值传递的时候,实际上是将实参的值赋值一份给形参
引用传递
Test2实例,Test3反例
传递的并不是实际的对象,而是对象的引用,外部对引用对象的改变也会反映到源对象上,因为引用传递的时候,实际上是将实参的地址值赋值一份给形参
创建类及初始化对象
使用new关键词创建对象
快捷键:new 对象.var
*构造器
public class Person(){
public Person(){
}
}
规则
- 必须和类名相同
- 必须没有返回值类型,也不能写void
- 实例化子类时会先调用父类的构造器,在调用子类的构造器,如果父类无法调用无参构造器,就需要子类通过super来调用有参构造器
作用
- 使用new关键词,本质是在调用构造器
- 初始化值
注意点
- 无参构造即使不定义也默认存在,但定义有参构造之后,如果再想使用无参构造,需提前定义一个无参的构造
- Alt+Insert 可快捷生成构造器
封装(oop.demo2.FengZhuang)
属性私有,get/set
在属性设为private私有后,实例化后是无法访问该私有属性的
可以设置get,set方法来获取和设置该属性(Alt+Ins)
继承(oop.demo3)
通过final修饰后的类不能继承
extends(Student、Person、Application)
子类继承父类,就会拥有该父类的所有公有方法 (子 extends 父)
ctrl+H 继承树(默认继承object类)
java中只有单继承,不能有多继承(一个儿子一个爸爸,一个爸爸可以有多个儿子)
super(Student1、Person1、Application1)
super与this相对,this输出当前对象属性,super是父类对象的
注意点
- super调用父类的构造方法,必须在构造方法的第一个
- super必须只能出现在子类的方法或者构造方法中
- super和this不能同时调用构造方法 (构造方法必须在第一行,都调用必然会有一个不在第一行)
前提
this:没有继承类也可以用
super:只能在继承条件下才能使用
构造方法
this():本类的构造方法
super():父类的构造方法
用法
super.print(); //调用父类的方法
System.out.println(super.name); //输出父类的name属性值
super()、this() //直接调用父类、子类的构造器
方法重写(A、B、Applicaition2)
方法覆盖就是子类有一个方法和父类的某个方法的名称、返回类型、参数一样,那我们就说子类的方法重写了父类的方法
规则
- 方法名必须相同
- 参数列表必须相同
- 修饰符:方位可以扩大但不能缩小: public > protect > default > private
- 抛出的异常:范围,可以被缩小,但不能扩大:ClassNotFoundException -->
Exception(大)
- 子类的方法和父类必须一直,方法体不同
为什么需要重写
父类的功能,子类不一定需要,或者不一定满足
Alt + Insert:override
静态与非静态方法区别
静态方法:方法的调用只和左边定义的数据类型有关
A a = new A();
a.test();
B b = new A();
b.test();
//结果:
A=>test()
B=>test()
非静态方法:重写
运行上述代码结果:
A=>test()
A=>test()
重写后有如下标志
多态(oop.demo4)
同一方法可以根据发送对象的不同而采用多种不同的行为方式
条件(Student、Person、Application)
- 有继承关系
- 子类重写父类方法
- 父类引用指向子类对象 -> Father f1=new Son();
注意点
- 多态是方法的多态,属性没有多态
- 父类和子类要有联系 例:Student类也可用Object类表示
- static方法、final常量、private方法不能用多态
规则
设 Student 子类 Person父类
- Student 能调用的方法都是自己或者继承父类Person的方法
- Person父类可以指向Student子类,但不能调用子类特有的方法
- 子类重写了父类的方法,会执行子类的方法
实例1:
当Student中没有run方法,执行student.run();时会调用 父类Person中的run方法输出run
当Student中有run方法后,方法重写则会执行子类Student中的run方法,输出son
实例2:
package Sentiment.array;
class Person5{
public String name;
public Person5(){
name="person";
}
public String getName() {
return name;
}
}
class Student5 extends Person5 {
public String name;
public Student5(){
name="Student";
}
public String getName() {
return name;
}
}
public class test{
public static void main(String[] args) {
Person5 person5 = new Student5();
System.out.println(person5.name); //结果 person
System.out.println(person5.getName());//结果 Student
}
}
原因:子类重写了父类的方法getName(),会执行子类的方法getName(),但属性name不会
Instanceof(Student、Person、Teacher、Application1)
Student、Teacher是Person的子类,Application1用于测试
定义
测试左边的对象是否是它右边的类的实例,返回 boolean 的数据类型。
个人理解
看了很多资料只是表示了左边的对象是否是它右边的类的实例 的一个概念,但并未标明false和编译报错之间的关系,于是记录下个人理解 (仅供参考)
true
没啥好说的,左边的对象是它右边的类的实例
false
对象y不是类z的实例,但x、z之间存在父子类关系
编译报错
对象y不是类z的实例,且x、z之间不存在父子类关系
注意点
- 把子类转换为父类,即向上转型不需要类型转换
//编译出错
Student a = new Person();
//正常执行
Person a = new Person();
Person a = new Student();
- 把父类转换为子类,即向下转型需要进行类型转换
Student a = new Person();
//上述会编译出错,无法将父类转换为子类,所以需要类型转换
Student b = (Student) a;
- 父类引用指向子类的对象 ,子类引用不可以指向父类对象
Person a = b //父类引用a指向子类对象b
static关键字(oop.demo5)
用法(Student)
当age设为静态变量后可以通过类直接调用,而age则编译出错;再实例化后都可用对象调用,而静态变量age也可以直接输出
匿名代码块(Person)
在对象实例化后会先调用静态代码块,然后调用匿名代码块,随后在调用构造器
{
//匿名代码块
}
静态代码块
静态代码块只调用一次
{
//静态代码块
}
静态导入包(Test)
正常情况下直接调用数学函数会报错
但通过静态导入包即import static xxx.xxxx.xxxx 后即可直接调用
抽象类(oop.demo6)
只有方法名,没有方法的实现
public abstract 类型 方法();
Alt+Inser 实现方法
注意点
- abstract修饰符可以用来修饰方法也可以修饰类
- 不能new抽象类,只能靠子类去实现
- 抽象类中可以写普通的方法,抽象方法必须写在抽象类中
- 子类继承抽象类,就必须实现抽象类中的抽象方法,否则需要声明为抽象类
接口(oop.demo7)
普通类:只有具体实现
抽象类:具体实现和规范(抽象方法)
接口:只有规范,自己无法写方法
接口可以多继承,extends只能单继承
作用
- 定义一些方法,让不同人实现(多个人可以同时实现一个接口)
- 方法定义:pulic abstract 常量定义:public static final
- 接口不能被实例化,接口中没有构造方法
- implements可以实现多个接口
- 必须要重写接口中的方法
内部类(oop.demo8)
成员内部类
在类中,新建个类
静态内部类
加上static即可,底层优先执行
局部内部类
pulic类下,创建的类都是局部内部类,一个java只能有一个public类
匿名内部类
可以对接口进行实例化
异常
Throwable类
java把异常当做对象来处理,java.lang.Throwable作为所有异常的超类
分类
Error
Error类对象由Java虚拟机生成并抛出,大多数错误与代码编写者所执行的操作无关。
Exception
运行时异常
- RuntimeException(运行时异常)
非运行时异常
- ArrayIndexOutOfBoundsException(数组下标越界)
- NullPointerException(空指针异常)
- ArithmeticException(算术异常)
- MissingResourceException(丢失资源)
- ClassNotFoundException(找不到类)
这些异常是不检查异常,程序中可以选择捕获处理,也可以不处理。
区别
- Error通常是灾难性的致命的错误,是程序无法控制和处理的,当出现这些异常时,Java虚拟机(JVM)一般会选择终止线程。
- Exception通常情况下是可以被程序处理的,并且在程序中应该尽可能的去处理这些异常。
异常处理机制
捕获异常
- try catch 结构
- try catch finally结构
在执行a/b时,由于0不能作为除数,即报出ArithmeticException异常
public class Test {
public static void main(String[] args) {
int a=1;
int b=0;
System.out.println(a/b);
}
}
根据ArithmeticException类型进行异常捕获,快捷键:Ctrl+Alt+T
public class Test {
public static void main(String[] args) {
int a=1;
int b=0;
try { //try监控区域
System.out.println(a/b);
} catch (ArithmeticException e) { //catch(想要捕获的异常类型)
System.out.println("算数异常");
} finally { //finally 关闭捕获防止资源占用
System.out.println("finally");
}
}
}
//结果:
算术异常
finally
若需要多个捕获异常则异常需要从小到大排序Throwable > Exception = Error > ArithmeticException……,如下若Throwable、Exception互换则会编译出错
public class Test {
public static void main(String[] args) {
int a=1;
int b=0;
try { //try监控区域
System.out.println(a/b);
} catch (Error e) { //catch(想要捕获的异常类型)
System.out.println("Error");
} catch (Exception e){
System.out.println("Exception");
} catch (Throwable e){
System.out.println("Throwable");
}
}
}
//结果
Exception
抛出异常
throw
- throw用在方法内
throws
- throws用在方法声明后
public class Test {
public static void main(String[] args) {
new Test().test(1,0); //匿名内部类
}
public void test(int a,int b) {
if(b==0){
throw new ArithmeticException(); //throw方法内抛出异常
}
}
}
throws在方法上抛出异常,使用时一般需要异常捕获
public class Test {
public static void main(String[] args) {
try {
new Test().test(1,0); //匿名内部类
} catch (ArithmeticException e) {
e.printStackTrace();
}
}
public void test(int a,int b) throws ArithmeticException{
if(b==0){
throw new ArithmeticException(); //throw方法内抛出异常
}
}
}
自定义异常
自定义异常必须继承Exception类或RuntimeException类
public class MyException {
public static void main(String[] args) {
new MyException().test(110);
}
public void test(int a){
if(a>120||a<10){
throw new AgeException("年龄需要在10-120之间");
}
System.out.println("输入正确");
}
}
class AgeException extends RuntimeException{
public AgeException(String message) {
super(message);
}
}
一般情况下,继承RuntimeException类,因为可以使用默认的处理机制,若继承Exception则需要再用throws抛出,即:
public class MyException {
public static void main(String[] args) throws AgeException {
new MyException().test(110);
}
public void test(int a){
if(a>120||a<10){
throw new AgeException("年龄需要在10-120之间");
}
System.out.println("输入正确");
}
}
class AgeException extends Exception{
public AgeException(String message) {
super(message);
}
}