Java笔记—Java面向对象和异常
这是目录
第二章 面向对象
1. 面向对象概念
- 面向过程VS面向对象
- 面向过程:步骤清晰第一步第二步适合处理规模不大的简单问题。(线性)
- 面向对象(OOP):分类思维模式,解决问题需要哪些分类,然后对这些分类进行单独思考,最后才对某个分类下的细节进行面向过程的探索,适合处理复杂问题和处理需多人协作的问题。
- 面向对象编程的本质:以类的方法组织代码,以对象的组织封数据。
-
break和return的区别
return除了返回值外也有中断函数执行的作用
break是中断当前循环
- 抽象: 忽略细节,抽出大家都像的部分
- 三大特性:封装,继承,多态
- 从认识论的角度看,是先有对象后有类。对象是具体事物,类是抽象的,对对象的抽象。
- 从代码运行的角度看是现有类后又对象,类是对象的模板
回顾方法:
补充:
-
在不同类中非静态方法的调用
静态方法可以直接在另一类中调用,
Student类
package com.htk.ood;
import java.io.IOException;
//类
public class Student {
//静态方法 static
//main 方法
public static void main(String[] args) {
}
//静态方法 static
// 修饰符,返回值类型,方法名(……)
//有返回值
public static String sayHello() {
return "Hello World!";
}
//非静态方法 无法在另一个类中直接使用,需要实例化这个类
//无返回值
public void hello(){
System.out.println("Hello World!");
}
//补充:完整的方法定义
public void readFile(String File) throws IOException{
}
}
Demo02类
package com.htk.ood;
public class Demo02 {
public static void main(String[] args) {
//实例化这个类 非静态方法在其他类里的调用方式
//对象类型 对象名 = 对象值
Student student = new Student();
student.hello();
//静态方法直接调用
System.out.println(Student.sayHello());
}
}
-
同一个类中,静态方法和非静态方法之间调用
静态方法不能调用非静态方法,会报错,原因是静态方法与类一起创建,费静态方法适合对象一起创建,先后次序有别。
2. 类和对象的创建分析
类和对象的关系
- 类是一种抽象的数据类型,它是对某一类事物整体描述/定义,但是并不能代表某一个具体事物
- 动物,植物,人,猫,狗
- 对象是抽象概念的具体事例
- 张三,张三家里的那只叫旺财的狗
创建与初始化对象
-
一个项目应该只有一个main()方法
-
package com.htk.ood; public class Application { public static void main(String[] args) { //Application类用于测试,只有一个入口 } }
-
学生类,一个类只由两部分组成 属性和方法
-
package com.htk.ood; import java.io.IOException; //学生类 public class Student { //属性 String name; int age; int studentNumber; char gender; String home; //方法 public void study(){ System.out.println(this.name+"正在学习"); } public void game(){ System.out.println(this.name+"正在玩游戏"); } }
-
-
使用new关键字创建对象:使用new关键字创建的时候除了分配内存空间之外,还会给出创建好的对象进行默认的初始化,以及对类中构造器的调用。
-
package com.htk.ood; public class Application { public static void main(String[] args) { //Application类用于测试,只有一个入口 //实例化类 用new关键字 Student zhangsan=new Student(); zhangsan.name="张三"; zhangsan.age=18; zhangsan.studentNumber=20200001; zhangsan.gender='男'; zhangsan.home="北京"; System.out.println(zhangsan.name+"在干嘛?"); zhangsan.study(); Student xiaomin=new Student(); xiaomin.name="小明"; xiaomin.age=18; System.out.println(xiaomin.name+"在干嘛?"); xiaomin.game(); } }
-
-
构造器必须掌握,一个类即使什么都不写,它也会存在一个方法
-
package com.htk.ood; import java.io.IOException; //学生类 public class Student { //属性 String name; int age; int studentNumber; char gender; String home; //方法 //构造方法,作用:实例初始化 //1.new关键字,必须要有构造器 public Student(){ this.name="King"; } //有参构造方法 //注意:一旦定义了有参构造方法,无参构造必须显示定义 public Student(String name){ this.name = name; } }
-
-
类中的构造器也称为构造方法,是对进行创建对象的时候必须要调用的,并且构造器有以下两个特点:
- 必须和类同名
- 必须没有返回类型,也不能写void
-
在IDEL中 alt+insert 选择constructed 快速完成构造方法
内存分析
总结:
-
类和对象:类抽象,对象具体
-
方法:定义和调用
-
对应的引用:基本类型,对象使用过引用来操作的:栈–>堆
-
属性:字段Field 或叫成员变量
默认初始化:0 null false
修饰符
-
对象的创建和使用
new关键字
构造器
-
类:属性和方法
3. 面向对象三大特性
3.1 封装
-
该露的露,该藏的藏
- 程序设计追求 “高内聚,低耦合”。高内聚就是类的内部数据细节由自己完成不允许外部干涉,低耦合:仅暴露少量的方法给外部使用。
-
封装(数据的隐藏)
- 通常,应禁止直接访问一个对象中数据的实际表示,而通过操作接口来访问,这称为信息隐藏。
- 封装的意义可以提高程序安全性,隐藏代码细节,统一接口,提高系统的可维护性。
-
属性私有(private修饰符),get/set(提供一些可以操作这个属性的方法,public的get或get的方法)
- alt+insert 可以快速生成get/set
package com.htk.ood;
import java.io.IOException;
//学生类
public class Student {
//属性
private String name;
private int age;
private char gender;
//方法
public String getname(){
return this.name;
}
public void setName(String name){
this.name = name;
}
public int getAge() {
return age;
}
//封装的意义可以提高程序安全性,隐藏代码细节,统一接口,提高系统的可维护性。
public void setAge(int age) {
if(age<0||age>120)
System.out.println("非法输入");
else
this.age = age;
}
public void study(){
System.out.println(this.name+"在学习");
}
}
package com.htk.ood;
public class Application {
public static void main(String[] args) {
/*
Application类用于测试,只有一个入口
实例化类 用new关键字
*/
Student zhangsan=new Student();
zhangsan.setName("张三");
System.out.println(zhangsan.getname()+"在干嘛?");
zhangsan.study();
}
}
3.2 继承
-
继承的本质是对某一批类的抽象,从而实现对现实世界更好的建模。
-
extends是扩展的意思,子类是父类的扩展。
-
java中类只有单继承,没有多继承。 1(父)对多(子)
-
继承是类与类之间的一种关系,除此之外,类和类之间的关系还有依赖,组合,聚合等
-
子类继承父类,使用关键字extends来表示
Object类
- 在IDEL中 ctrl + H 会出现继承树状关系
- 在java中所有的类,都默认继承Object类
- 贯穿java学习整个过程
super
- super调用分类的构造方法,必须在构造方法的第一个 ,super()在无参构造里必须在第一个
- super必须只能出现在子类的方法或者构造方法中
- super和this不能同时调用构造方法!
- 与this相比
- 代表对象不同:
- this:本身调用者对象
- super:代表父类对象的应用
- 前提不同:
- this:没有继承也可以使用
- super:只能在继承时使用
- 构造方法不同:
- this():本类的构造
- super():父类的构造
- 代表对象不同:
package com.htk.ood;
public class Application {
public static void main(String[] args) {
/*
Application类用于测试,只有一个入口
实例化类 用new关键字
*/
Student student = new Student();
student.test();
student.pTest();
}
}
package com.htk.ood;
public class Person {
//属性
protected String name = "God";
//方法
public void printTest(){
System.out.println(this.name);
}
}
package com.htk.ood;
//学生类
public class Student extends Person{
//属性
String name = "xiaolaji";
//构造方法的super
public Student(){
//spuer() 隐藏的代码,必须在第一位
}
//方法 private的东西无法继承
//属性上super
public void test(){
System.out.println(name);
System.out.println(this.name);
System.out.println(super.name);
}
public void printTest(){
System.out.println(this.name);
}
//方法上super
public void pTest(){
printTest();
this.printTest();
super.printTest();
}
}
方法重写
-
重写都是方法的重写,与属性无关,且要有继承关系作为前提
-
父类的引用指向了子类,A继承B ,B b = new A();
-
有static,final,private修饰词不能重写
-
静态方法和非静态方法区别很大
- 非静态方法(public)—子类重写了父类的方法
-
方法名必须相同,参数列表必须相同,方法体不同。
-
修饰符:范围可以扩大,但不能缩小 public>protected>Default>private
-
抛出异常:范围,可以被缩小但不能扩大,ClassNotFoundException—>Exception
-
重写的意义:父类的功能子类不一定都需要
3.3 多态
-
一个对象的实际类型是确定的,但可以指向对象的引用的类型有很多 (父类)
-
多态是方法的多态,属性没有多态
-
父类和子类有联系,防止出现类型转换异常 ClassCastException
-
存在的条件: 继承关系,方法需要重写,父类引用指向子类对象 father f = new son();
-
对象能执行哪些方法主要看对向左边的类型,和右边关系不大!
-
instanceof (类型转换)引用类型 (Object > 父类 > 子类)
-
必须有联系,高可以低,同级之间会报错
-
System.out.println(x instanceof y); //x,y必须是子父类关系,且x必须是y的子类 //父转子 Person student = new Student(); ((student) student).go(); //强制类型转换 //子转父 Student student = new Student(); Student.go(); Person person = student;
-
子类转换为父类,可能丢失自己的本来的一些方法!
-
总结:
- 父类引用指向子类的对象
- 子类转换父类,向上转型,直接转换。
- 父类转换为子类,线下转型;强制类型转换。
- 方便调用,减少重复的代码!
4. static关键字
package com.htk.ood;
public class DemoStatic {
private static int age; //静态变量 多线程
private double sorce; //非静态变量
public static void main(String[] args) {
DemoStatic s1=new DemoStatic();
System.out.println(s1.age);
System.out.println(s1.sorce);
System.out.println(DemoStatic.age);
System.out.println(DemoStatic.sorce); //掉用不了没有static
say();
run(); //无法调用 ,没静态。
new DemoStatic().run(); //这样可以调用
}
//静态方法
public static void say(){
}
//非静态方法
public void run(){
}
}
-
匿名代码块和静态代码块
-
package com.htk.ood; public class DemoStatic { { //匿名代码块,赋初始值 System.out.println("匿名代码块"); } static { //静态代码块,只执行一次 System.out.println("静态代码块"); } private static int age; //静态变量 多线程 private double sorce; //非静态变量 public static void main(String[] args) { DemoStatic s1=new DemoStatic(); System.out.println(s1.age); System.out.println(s1.sorce); System.out.println(DemoStatic.age); System.out.println(DemoStatic.sorce); //掉用不了没有static say(); run(); //无法调用 ,没静态。 new DemoStatic().run(); //这样可以调用 } //静态方法 public static void say(){ } //非静态方法 public void run(){ } }
-
静态导入包
-
import static java.lang.Math.random;
5. 抽象类和接口
抽象类
- abstrac修饰符,即可以修饰类也可以修饰抽象类的方法。
- 抽象类中可以没有抽象方法,但抽象方法一定在抽象类中。
- 抽象类不能用new关键字来创建对象,需要使用子类继承。
- 抽象方法只有方发声明没有方法实现。
- 子类继承抽象类就必须要实现抽象类没有实现的抽象方法,否则子类也要声明为抽象类。
package com.htk.ood;
//Abstract 抽象类: 类是单继承的 java没有多继承,但接口可以实现多继承
public abstract class Action {
String name ="抽象类带参构造方法";
//约束~有人帮我们实现
//抽象方法,只有方法名字,没有方法的实现!
public abstract void doSomething();
public Action() {
System.out.println("1");
}
/*
1.不能new这个抽象类,只能靠子类去实现它:约束。
2.抽象类中可以写普通方法
3.抽象方法只能在抽象类中
//抽象的抽象:约束
*/
}
package com.htk.ood;
public class ActionSon extends Action {
String name = "子类的带参构造方法";
@Override
public void doSomething() {
}
public ActionSon() {
System.out.println("2");
}
}
package com.htk.ood;
public class Application {
public static void main(String[] args) {
/*
Application类用于测试,只有一个入口
实例化类 用new关键字
*/
ActionSon a = new ActionSon();
System.out.println(a);
//抽象类存在构造器
}
}
抽象类的意义:提高开发效率
接口
-
普通类:只有具体实现
-
抽象类:具体时限和规范都有
-
接口:只有规范!
-
接口就是规范,定义的是一组规则,“如果你是……就必须……”。
-
接口的本质是契约。
-
面向对象的精髓就是对对象的抽象,最能体现的这一点的就是接口,如何合理的去抽象。
声明类的关键字是class,声明接口的关键字是interface
package com.htk.ood;
public interface UserService {
//接口里的常量都是public static final,不常用
String name="emmm";
//接口中的所有定义其实都是抽象的public abstract
//增删改查
void addUser(String name);
void deleteUser(String name);
void updateUser(String name);
void queryUser(String name);
}
package com.htk.ood;
public interface TimeService {
//接口里的常量都是public static final,不常用
String name="OK";
//增删改查
void Timer();
void queryUser(String name);
}
package com.htk.ood;
//使用implements实现接口,也可以实现多个接口用 , 分隔实现多继承
//实现类接口的类就必须重写借口的方法
public class UserServiceImp1 implements UserService,TimeService {
@Override
public void addUser(String name) {
}
@Override
public void deleteUser(String name) {
}
@Override
public void updateUser(String name) {
}
@Override
public void Timer() {
}
@Override
public void queryUser(String name) {
}
}
总结:
1.定义的方法让不同子类实现
2.public abstract 方法默认
3.public static final 常量默认
4.接口不能被实例化
5.可以实现多个接口,实现接口必须要实现接口的方法
6. 内部类介绍
内部类
- 内部类就是在一个类的内部在定义一个类,比如A类中定义一个B类,那么B类相对A类来说就称为内部类。A就是B的外部类
- 1.成员内部类
- 2.静态内部类
- 3.局部内部类
- 4.匿名内部类
第三章 异常
- 在程序运行过程中可能会遇到一些不期而至的异常问题,如输入不和要求,文件打开格式不对,找不到文件,数据读取不到,内存溢出或是满内存,网络连接失败等等。
- 异常发生在程序运行期间,它影响了正常的程序执行流程。
- 简单分类
- 检查型异常:用户错误或问题引起,无法预见
- 运行时异常:运行时异常是可以被程序员避免的异常,可在被编译时忽略
- 错误:错误不是异常,已经脱离了程序员控制的范围
- 异常体系结构
- Java把异常当做对象处理,并定义了一个基类java.lang.Throwable作为异常的超类。
- 在Java API中已经定义了许多异常类,这些异常类分为两大类,错误Error和异常Exception。
- Error里有虚拟机异常和AWT异常(GUI异常)。
- Exception里有IO异常和运行时异常等等。
1.Exception
- 在Exception分支中有一个重要子类RuntimeException(运行时异常),其余子类异常称为非运行时异常
- 与Error的区别就是:Error通常是灾难性致命错误,是程序无法控制和处理的,当出现异常时,JVM一般会选择终止线程,Exception通常情况下是可以被程序处理的,并且在程序中应该尽可能的去处理这些异常。
2.Error
- Error类对象由Java虚拟机生成并抛出,大多数错误与代码编写者执行的操作无关
- Java虚拟机运行错误,当JVM不再又继续执行操作所需的内存资源时,将出现OutOfMemoryError(内存溢出)。这些异常发生时,JVM一般会选择线程终止。还有发生在虚拟机执行应用时,如类定义错误,连接错误。这些错误是不可查的没因为他们在应用程序的控制和处理能力之外,而且绝大多数情况是程序运行时不允许出现的情况。
3.捕获或抛出异常
-
抛出异常
-
捕获异常
-
异常处理五个关键字:
-
try
-
catch
-
finally
-
throw
-
throws
-
package com.htk.Exception; import java.sql.SQLOutput; public class Demo01 { public static void main(String[] args) { int a=1; int b=0; //ctrl+alt+t 快速生成try-catch-finally //---try--catch---finally演示 try{ //监控区域 System.out.println(a/b); }catch (ArithmeticException e){ //捕获异常 catch(Throwable)捕获全部异常 System.out.println("出现ArithmeticException异常"); }finally { //善后,不管有无出现异常都会执行,可以不要finally System.out.println("建议被除数改为非零数"); } //--- catch(Throwable)捕获全部异常 演示,要遵循下上小的层层递进关系 //第一层就是Throwable的话下面的Error的子类都会被覆盖 try{ new Demo01().a(); }catch(Error er){ System.out.println("捕获Error"); }catch(Exception ex){ System.out.println("捕获Exception"); }catch (Throwable t){ System.out.println("捕获Throwable"); }finally { System.out.println("finally"); } //主动抛出异常 throw 常用在方法中抛出异常 new Demo01().div(1,0); //在方法上主动抛出异常 throws try { new Demo01().divi(1,0); } catch (ArithmeticException e) { e.printStackTrace(); } } public void a(){ b(); } public void b(){ a(); } //在方法内抛出异常 public void div(int a,int b){ if(b==0){ throw new ArithmeticException(); } System.out.println(a/b); } //在方法上抛出异常 public void divi(int a,int b)throws ArithmeticException{ if(b==0){ throw new ArithmeticException(); } System.out.println(a/b); } }
4.自定义异常
-
自定义类只需要继承Exception类(extends)
-
在程序中自定义异常类步骤:
- 创建自定义异常类
- 在方法中通过throw关键字抛出异常类
- 如果当前跑出异常的方法中处理异常,可以使用try-catch语句捕获处理,否则在方法的声明通过throws关键字指明要抛出给方法调用者的异常,继续进行下一步操作
- 在出现异常方法的调用者中捕获异常并处理异常。
package com.htk.Exception;
public class DiyException extends Exception {
//自定义一个数字大于10就会出现异常
private int digit;
//构造方法
public DiyException(int d){
this.digit = d;
}
//toString:异常的打印信息
@Override
public String toString() {
return "DiyException{" + "digit=" + digit + '}';
}
}
package com.htk.Exception;
import java.sql.SQLOutput;
public class Demo01 {
public static void main(String[] args) {
new Demo01().test(18); //测试
}
public void test(int a){
System.out.println("传递的参数为"+a);
if(a>10){
try {
throw new DiyException(a); //抛出异常
} catch (DiyException e) { //捕获异常
e.printStackTrace();
}
}
System.out.println(a);
}
}
- 总结
- 合理规避,同时辅助try-catch处理
- 在多重catch块后,可以加一个catch(Exception)来处理可能会被遗漏的异常
- 尽量不要printStackTrace(),去处理异常
- 尽量添加finally语句块去释放占用的资源