面向对象
构造器
类中的构造器也成为构造方法,是在进行创建对象的时候必须要调用的。而且构造器有以下两个特点:
-
1.必须和类的名字相同
-
2.必须没有返回类型,也不能写void
1.使用new关键字,本质是在调用构造器
2.有参构造:一旦定义了有参构造,无参就必须显示定义
public class Person{ String name; //Alt + Insert快捷生成 public Person(){ } public Person(String name){ this.name = name; } }
属性
字段Field 成员变量
默认初始化:
-
数字:0 0.0
-
char:u0000
-
boolean:false
-
引用:null
封装
封装(数据的隐藏)
-
通常,应禁止直接访问一个对象中数据的实际表示,而应通过操作接口来访问,这称为信息隐藏
属性私有,get/set
“高内聚,低耦合”
继承
-
extends的意思是“扩展”。子类是对父类的扩展。
-
JAVA中只有单继承没有多继承
-
继承是类与类之间的一种关系。除此之外,类和类之间的关系还有依赖、组合、聚合等
-
子类和父类之间,从意义上讲应该具有“is-a”关系
-
在java中所有的类,都默认直接或间接继承Object
super
1.super调用父类的构造方法,必须在构造方法的第一个
2.super必须只能出现在子类的方法或者构造方法中
3.super和this不能同时调用构造方法
重写
重写:需要有继承关系,子类重写父类的方法
父类的功能,子类不一定需要,或者不一定满足
1、方法名必须相同
2、参数列表必须相同
3、修饰符:范围可以扩大但不能缩小:public > protected > default > private
4.抛出的异常:范围可以被缩小但不能扩大 ClassNotFoundException ---> Exception(大)
public class B{ public void test(){ System.out.println("B"); } } public class A extends B{ //Override 重写 @Override //注解:有功能的注释 public void test(){ System.out.println("A") } } public class Application{ public static void main(String[] args){ //静态方法的调用只和左边,定义的数据类型有关 如果改成static //B b = new A(); //b.text();//B //非静态:重写 A a = new A(); a.text();//A B b = new A(); b.text();//A } }
多态
动态编译:类型
-
即统一方法可以根据发送对象的不同而采用多种不同的方法
多态注意事项:
1.多态是方法的多态,属性没有多态
2.父类和子类,有联系
3.存在条件:继承关系,方法需要重写,父类引用指向子类对象
static,final,private不能重写
public class Person{ public void say(){ System.out.println("1"); } } public class Student extends Person{ public void say(){ System.out.println("2"); } public void eat(){ System.out.println("eat"); } } public class Application{ public static void main(String[] args){ //Student 能调用的方法都是自己的或者继承父类的 Student s1 = new Student(); //父类可以指向子类,但是不能调用子类独有的方法 Person s2 = new Student(); s1.run();//2 s2.run();//2 //s2.eat(); } }
instanceof 类型转换
public class Person{ } public class Student extends Person{ } public class Teacher extends Person{ } public class Application{ public static void main(String[] args){ //Object > String //Object > Person > Teacher //Object > Person > Student //System.out.println(X instanceof Y);//能不能编译通过 看X是否与Y有关系 Object object = new Student(); System.out.println(object instanceof Student);//T System.out.println(object instanceof Person); //T System.out.println(object instanceof Object); //T System.out.println(object instanceof Teacher);//F System.out.println(object instanceof String); //F Person person = new Student(); System.out.println(person instanceof Student);//T System.out.println(person instanceof Person); //T System.out.println(person instanceof Object); //T System.out.println(person instanceof Teacher);//F //System.out.println(person instanceof String); //编译报错 Student student = new Student(); System.out.println(student instanceof Student);//T System.out.println(student instanceof Person); //T System.out.println(student instanceof Object); //T //System.out.println(student instanceof Teacher);//编译报错 //System.out.println(student instanceof String); //编译报错 } }
static
public class Student{ private static int age;//静态的变量 private double score;//非静态变量 public void run(){ } public static void go(){ } public static void main(String[] args){ Student s1 = new Student(); System.out.println(Student.age); System.out.println(s1.age); System.out.println(s1.score); Student.go(); go(); } }
public class Person{ //匿名代码块:用于赋初值 { System.out.println("匿名代码块"); } //static只执行一次 static{ System.out.println("静态代码块"); } public Person(){ System.out.println("构造方法"); } public static void main(String[] args){ Person person = new Person(); //静态代码块 //匿名代码块 //构造方法 Person person1 = new Person(); //匿名代码块 //构造方法 } }
//静态导入包 import static java.lang.Math.random;
抽象类
abstract修饰符可以用来修饰方法也可以修饰类
抽象类的方法,继承了它的子类,都需要实现它的方法,除非子类也是个抽象类
1.不能new抽象类,只能靠子类去实现它:约束
2.抽象类中可以写普通的方法
3.抽象方法必须在抽象类中
//abstract抽象类: 类extends单继承(接口可以多继承) public abstract class Action{ //抽象方法,只有方法名字,没有方法的实现 public abstract void doSomething(); } public abstract class A extends Action{ @Override public void doSomething(){ } }
接口
-
普通类:只有具体实现
-
抽象类:具体实现和规范(抽象方法)都有
-
接口:只有规范
接口就是规范,定义的是一组规则。
接口的本质是契约
OO的精髓,是对对象的抽象,最能体现这一点的就是接口。
//interface 定义的关键字,接口都需要有实现类 public interface UserService{ //接口里面的常量(不常用) int AGE = 99;//public static final int AGE = 99; //接口中的所有定义其实都是抽象的public void add(String name);//public abstract void add(String name); } public class UserServiceImpl implements UserService{ @Override public void add(String name){ } }
public interface UserService{ //接口中的所有定义其实都是抽象的public void add(String name); } public interface TimeService{ void timer(); } //利用接口 多继承 public class UserServiceImpl implements UserService,TimeService{ @Override public void add(String name){ } @Override public void timer(){ } }
接口的作用:
1.约束
2.定义一些方法,放不同的人实现
3.public abstract
4.public static final
5.接口不能被实例化,接口中没有构造方法
6.implements可以实现多个接口
7.必须重写接口中的方法
内部类
1.成员内部类
public class Outer{ private int id = 10; public void out(){ System.out.println("这是外部类的方法"); } public class Inner{ public void in(){ System.out.println("这是内部类的方法"); } //获得外部类的私有属性 public void getID(){ System.out.println(id); } } } public class Application{ public static void main(String[] args){ Outer outer = new Outer(); Outer.Inner inner = outer.new Inner(); inner.in; inner.getID(); } }
2.静态内部类
public class Outer{ private int id = 10; public static class Inner{ //获得不了外部类的私有属性 //public void getID(){ // System.out.println(id); //} } } public class Application{ public static void main(String[] args){ Outer outer = new Outer(); Outer.Inner inner = outer.new Inner(); //inner.getID(); } }
3.局部内部类
public class Outer{ public void method{ class Inner{ } } }
4.匿名内部类
class Apple{ public void eat(){ } } interface UserService{ } public class Test{ public static void main(String[] args){ //没有名字初始化类,不用将实例保存到变量中 new Apple().eat(); UserService userService = new UserService(){ @Override public void hello(){ } } } }
异常机制
(Error & Exception)
异常指程序运行中出现的不期而至的各种状况
-
检查性异常:最具代表的检查性异常是用户错误或问题引起的异常,这是程序员无法预见的。例如要打开一个不存在文件时,一个异常就发生了,这些异常在编译时不能被简单地忽略
-
运行时异常:运行时异常是可能被程序员避免的异常。与检查性异常相反,运行时异常可以在编译时被忽略
-
错误Error:错误不是异常,而是脱离程序员控制的问题。错误在代码中通常被忽略。例如当栈溢出时,一个错误就放生了,它们在编译也检查不到
Error
大多数错误与代码编写者所执行的操作无关
Exception
这些异常一般是由程序逻辑错误引起的,程序应该从逻辑角度尽可能避免这类异常的发生
Error和Exception的区别
Error筒仓是灾难性的致命的错误,是程序无法控制和处理的,当出现这些异常时,java虚拟机(JVM)一般会选择终止线程;Exception通常情况下是可以被程序处理的,并且在程序中应该尽可能的去处理这些异常
异常体系结构
java把异常当做对象来处理,并定义一个基类java.lang.Throwable作为所有异常的超类
异常处理五个关键字:try,catch,finally,throw,throws
抛出异常
捕获异常
public class Test{ public static void main(String[] args){ int a = 1; int b = 0; //假设要捕获多个异常:从小到大列 //Ctrl + Alt + T 快捷生成 try{//try监控区域 if(b==0){//throw throws throw new ArithmeticException;//主动抛出异常,一般在方法中使用 } System.out.println(a/b); }catch(ArithmeticException e){//catch(想要捕获的异常类型) 捕获异常 System.out.println("ArithmeticException"); }catch(ThrowAble e){ System.out.println("ThrowAble"); }finally{//处理善后工作 System.out.println("finally"); } //finally 可以不要finally, 一般用于IO,资源关闭 } }
自定义异常
public class MyException extends Exception{//自定义异常要继承Exception类 //传递数字,如果大于10就抛出异常 private int detail; public MyException(int a){ this.detail = a; } //toString 异常的打印信息 @Override public String toString(){ return "MyException{" + detail + '}'; } } public class Test{ //可能会存在异常的方法 static void test(int a) throws MyException{ if(a>10){ throw new MyException(a);//抛出 } } }
实际应用中的经验总结
-
处理运行时异常时,采用逻辑去合理规范同时辅助try-catch处理
-
在多重catch块后面,可以加上一个catch(Exception)来处理可能被遗漏的异常
-
对于不确定的代码,也可以加上try-catch,处理潜在的异常
-
尽量去处理异常,切忌只是简单地调用printStackTrace()去打印输出
-
具体如何处理异常,要根据不同的业务需求和异常类型去决定
-
尽量添加finally语句块区释放占用的资源,IO,Scanner