Java高级教程
程序员文章站
2022-07-05 15:37:49
[TOC] 1.Java面向对象方法 继承 封装 多态 this的用法 引用隐式参数 调用该类其他的构造器 super的用法 调用超类方法 调用超类的构造器 1.1. 创建类和对象的方法 对象和引用的一个关系图: 模板: 下面是一个简单的实例 1.2. this的使用 使用this调用成员变量和成员 ......
目录
1.java面向对象方法
- 继承
- 封装
- 多态
this的用法
- 引用隐式参数
- 调用该类其他的构造器
super的用法
- 调用超类方法
- 调用超类的构造器
1.1. 创建类和对象的方法
对象和引用的一个关系图:
模板:
class classname { field1 // 属性: 描述类的状态 field2 ... constructor1 constructor2 ... method1 // 方法: 描述类的行为 method2 }
下面是一个简单的实例
public class main { public static void main(string[] args) throws ioexception { // 对象的使用方法 // 对象.变量: staff.name // 对象.函数(): staff.getname() employee[] staff = new employee[3]; staff[0] = new employee("zhang", 75000, 1977, 12,15); staff[1] = new employee("li", 23000, 1932, 3,5); staff[2] = new employee("zhang", 56444, 1964, 6,21); for (employee e: staff){ e.raisesalary(5); } for (employee e: staff){ system.out.println("name=" + e.getname() + ", salary=" + e.getsalary() + ", hireday=" + e.gethireday()); } } } // 一个类可以有无限多个对象 class employee{ // 三个实例域用来存放将要操作的数据 private string name; private double salary; private localdate hireday; // 构造器(与类名同名),总是伴随着new操作符的执行而被调用 // 每个类可以有一个以上的构造器 // 如果类中没有构造器,java会默认有一个构造器用于初始化 // 但是如果类的构造器大于1个的话,需要自己构造默认构造器 // 构造器可以有0,1,...等多个参数 // 构造器没有返回值,即没有void // 构造器总是伴随着new的操作一起调用 public employee(string n, double s, int year, int month, int day){ name = n; salary = s; hireday = localdate.of(year, month, day); } // 需要获得或者设置实例域的值,需要提供以下三个内容: // (1).一个私有的数据域 // (2).一个公有的域访问器方法 // (3).一个公有的域更改器方法 public string getname() { return name; } public double getsalary() { return salary; } public localdate gethireday() { return hireday; } public void sethireday(localdate hireday) { this.hireday = hireday; } public void setname(string name) { this.name = name; } public void setsalary(double salary) { this.salary = salary; } // class方法有两个参数: 显示参数(括号内部的参数) + 隐式参数(引用该方法的对象) // 用this来表示隐式参数,表示使用该方法的对象 public void raisesalary(double rate){ // 可以直接访问类的属性 double raise = this.salary * rate / 100; this.salary = this.salary + raise; } }
1.2. this的使用
- 使用this调用成员变量和成员函数
- 使用this调用构造函数
class person{ string name; int age; string address; person(){ system.out.println("无参数"); } person(string s, int a){ this.nanme = s; this.age = a; } // this可以调用构造函数 person(string s, int a, string s2){ this(s, a); this.address = s2; } // this为使用该方法的对象,也称为类的隐式参数 void talk(){ system.out.println("my name is " + this.name) } }
1.3. 静态域和静态方法
1.3.1. 静态域:属于类的级别
- 一般变量:
对象.变量
- 静态变量:
类名.变量
+对象.变量
如果将一个域定义为static, 每个类中只有一个这样的域, 而每个对象对于所有的实例域却有自己的一份拷贝, 比如我们创建一个class:
class employee { private static int nextid = 1; private int id; }
如果有1000getemployee类的对象,就有100个实例域id,但是只有一个静态域nextid
1.3.2.静态常量
// 1000个对象有1000个拷贝 public final double pi = 3.14; // 1000个对象只有一个pi public static final doube pi = 3.14;
1.3.3 静态方法
静态方法是一种不能向对象实施操作的方法,只能通过类名调用,也就是说没有this隐式参数
- 非静态方法:
employee.getnextid()
- 静态方法:
employee.getnextid()
- 静态函数中不能使用非静态变量(非静态域)
1.3.4. 工厂方法
1.3.5. main方法
public class main { // main是一个静态方法,不对任何对象进行操作 // 事实上,再启动程序的时候没有任何对象,静态main方法将执行并创建程序需要的对象 public static void main(string[] args) { system.out.println("hello world!"); } }
1.4. 对象构造
1.4.1. 对象重载
如果多个方法有相同的名字、不同的参数,便产生了重载,编译器根据传入的参数自动旋转哪个方法
stringbuilder msg = new stringbuilder(); stringbuilder msg = new stringbuilder("to do: \n");
1.4.2. 类的构造器以及初始化
class employee { private static int nextid; private int id; private string name; private double salary; //初始化块中初始化值 { id = nextid; nextid++; } // 构造器中初始化值 public employee(){ name = "" salary=0; } public employee(string n, double s){ this.name = name; this.salary = s; } }
1.5. 包
管理class文件的
- 导入类文件:
import java.util.*
- 将类文件放到包中:
package com.horstman.corejava
2. java的继承
一个类得到了另外一个类的成员变量和成员函数
java只支持单继承,不允许多继承
2.1. 继承的语法
public class main { public static void main(string[] args) { // 生成子类的过程 student st = new student("zhang", 20, 6); st.introduce(); } } // 将重复代码放到父类中去 class person{ string name; int age; public person(){ system.out.println("person无参数"); } public person(string name, int age){ this.name = name; this.age = age; } void eat(){ system.out.println("吃饭"); } void introduce(){ system.out.println("my name is " + this.name + ", my age is " + this.age); } } class student extends person{ int grade; // 自动继承父类的成员变量和成员函数 // 在子类的构造函数中,必须调用父类的构造函数 public student(string name, int age, int grade) { super(name, age); this.grade = grade; } // 子类可以写自己的成员函数 void study(){ system.out.println("study"); } // 复写 父类的方法 // 1. 在具有父子关系的两个类当中 // 2. 父类和子类中各有一个函数,这两个函数的定义(返回值类型,函数名和参数列表)完全相同 @override void introduce() { super.introduce(); system.out.println("my grade is " + this.grade); } }
2.2. 继承中的对象转型
2.2.1. 对象向上转型
将子类的对象赋值给父类的引用
// s是学生,也是人 //s: 变量(name,age,address) + 函数(introduce, study) student s = new student(); //p:变量(name,age) + 函数(introduce) person p = s; // 一个引用能够调用哪些成员变量和函数,取决于这个引用的类型(p引用person,看p前面的类型) // 一个引用调用的哪个方法,取决于这个引用所指向的对象(p指向的是student对象,调用student方法) p.name = "zhang"; p.age = 12; // p.address = "bj" 不可以使用(他说) p.introduce(); // 调用的是子类的introduce() // p.study() 不可以使用
2.2.2. 对象向下转型
student s1 = new student(); person p = s1; student s2 = (student)p;
2.3. 阻止继承:final类和方法
- 将类定义为final后,无法继承
- 将类的方法定义为final后,子类无法覆盖该方法
public class final mother extends person{ ....; } public class student extends person{ public final string getname{ ....; } }
2.4.抽象类和抽象函数
面向对象思想:先抽象,后具体
2.4.1. 定义方法与语法特征
- 只有函数的定义,没有函数体的函数
- 抽象类不能生成对象(如果能的话,可能调用抽象函数,但是抽象函数没有函数体,无法解释)
- 抽象类天生是当爹的,只能被继承,它的子类可以生成对象
- 如果一个类中包含抽象函数,那么类必须被声明为抽象类
- 如果一个类中没有抽象函数,也可以声明为抽象类
- 抽象类可以有构造函数
public class main { public static void main(string[] args) { person p = new chinese(); p.eat(); } } // 抽象类 abstract class person{ string name; int age; public person(){ system.out.println("person无参数"); } public person(string name, int age){ this.name = name; this.age = age; } // 抽象函数 abstract void eat(); void introduce(){ system.out.println("my name is " + this.name + ", my age is " + this.age); } } class chinese extends person{ chinese(){ super(); system.out.println("chinese的构造函数"); } @override void eat() { system.out.println("用筷子吃饭"); } }
2.4.2. 为什么用抽象类?
- 抽象类表达的是一种抽象的概念,属于比父类还抽象的类
- 抽象函数可以检查子类是否复写了抽象函数,是一种检测机制,检测是否子类有没有写应该复写的抽象函数
public class main { public static void main(string[] args) { person[] p = new person[2]; p[0] = new employee("zhang",5000,2018,10,12); p[1] = new student("li", "cs"); // i.getdescription()中由于不能构造抽象类person的对象,所以变量i永远不会引用person对象,而是引用employee或者student子类的具体对象 for (person i:p){ system.out.println(i.getname() + "," + i.getdescription()); } } } // 将重复代码放到父类中去 abstract class person{ abstract string getdescription(); string name; person(string name){ this.name=name; } public string getname() { return name; } } class employee extends person{ double salary; localdate hireday; employee(string name,double salary, int year, int month, int day){ super(name); this.salary = salary; hireday = localdate.of(year,month, day); } public double getsalary() { return salary; } @override public string getname() { return super.getname(); } public localdate gethireday() { return hireday; } @override string getdescription() { return string.format("an employee with a salary of %.2f", salary); } } class student extends person{ string major; student(string name, string major){ super(name); this.major = major; } @override public string getname() { return super.getname(); } public string getmajor() { return major; } @override string getdescription() { return "a student majoring in" + major; } }
zhang,an employee with a salary of 5000.00 li,a student majoring incs
3. 包的访问权限
3.1. 将类放到包中
什么是软件包?
怎么讲类放到软件包中?
- 将类放到一个包中,需要使用packcage “包名”
- 编译时需要使用 -d参数,该参数的作用是依照包名生成相应的文件夹
- 一个类的全名: 包名 + . + 类名:mars.test
- 包名的命名规范
- 一般小写
- 一般是域名倒过来写:
io.github.com.haochen95
;
- 一般小写
package mars; class test{ public static void main(string[] args){ system.out.println("package") } }
3.2. 包的访问权限有哪些
访问权限 | 含义 | 包内可否使用 | 包之间可否使用 | 包内继承 | 包间继承 |
---|---|---|---|---|---|
public | 公有权限 | yes | yes | yes | yes |
private(很少修饰类) | 私有权限 | no | no | no | no |
default | 包级别访问权限 | yes | no | yes | no |
protected(不修饰类) | 受保护权限 | yes | no | yes | yes(只有子类才能使用) |
- 如果子类和父类不在同一个包中,子类确实继承到了父类的成员变量和成员函数,然后再检查权限,看是否能够使用
public > protected > default > private
4. 接口
4.1. 什么是接口
4.2.接口语法
- 使用interface定义
- 接口中的方法全是抽象方法
- 接口中的方法全是public权限
- 实现接口使用implements关键字
- 一个类可以实现多个接口
- 一个接口可以继承多个接口
// 定义接口 interface usb{ public void read(); public void write(); } interface wifi{ public void open(); public void close(); } // 继承接口 class phone implements usb,wifi{ public void read(){ system.out.println("usb read") } public void write(){ system.out.println("usb wrute") } public void open(){ system.out.println("wifi open") } public void close(){ system.out.println("wifi close") } } // 主函数中调用 class test{ public static void main(string[] args){ phone phone = new phone(); usb usb = phone; usb.read(); usb.write(); wifi wifi = phone; wifi.open(); wifi.close(); } }
4.3. 接口的应用
- 在继承中,可以将重复代码放到父类中
- 但是所有子类都需要使用类似的方法体,可能使用接口更加的合适
- 接口定义了一种标准,接口只定义应该有这些方法,但是不关心方法的具体实现方法,由每个子类自己去实现
5. java的异常处理
5.1. jdk异常的分类和try-catch捕捉
- 异常:终端了正常指令流的事件;
- 程序在异常处会中断,退出程序
- 使用try-catch捕捉异常(对于track error必须使用)
try{ system.out.println(4); // 没出异常,继续执行/出了异常跳到catch执行,再继续执行 } catch(exception e){ e.printstacktrace(); system.out.println(5); } finally{ // 异常出不出 都会执行这个程序-----主要用于io流的关闭文件代码 system.out.println(6); } system.out.println(7);
5.2. 用户自定义的异常处理
- throw和throws关键字的用法
public void setage(int age){ if(age<0){ // untrack excaption---程序运行到这里就会终止 runtimeexception e = new runtimeexception("年龄不能为负数"); throw e; // track excaption --- 必须用try-catch进行捕捉或者声明(throws exception)放在类声明中 exception e = new exception("年龄不能为负数") throw e; } }
6. java中的io
6.1. io的定义和分类,以及字节流基本用法:
- io的目标:从数据源(文件,键盘,网络)中读取数据,从数据写入到数据目的地(文件,屏幕,网络)当中
- 输入和输出流在java中都设置成一种"管道", io流也是一种对象
- io的分类
- 输入输出流
- 字节流,字符流
节点流,处理流
io流中的核心类:
inputstream(抽象类) <- fileinputstream
,outputstream(抽象类) <-fileoutputstream
-inputstream: int read(byte[] b, int off, int len)
,返回读取了多少字节的数据
-outputstream: void write(byte[] b, int off, int len)
import java.io.*; // 字节流 class test{ public static void main(string[] args){ // 声明输入流引用 fileinputstream fis = null; // 声明输出流引用 fileoutputstream fos = null; try{ // 字节流-读数据: 生成代表输入流的对象 fis = new fileinputstream("d:/from.txt"); // 生成代表输出流的对象 fos = new fileoutputstream("d:/to.txt"); // 生成一个字节数组 byte[] buffer = new byte[100]; // 调用输入流的read方法,读取数据 int temp = fis.read(buffer, 0, 100); // 写入到文件中 fos.write(buffer,0, temp); string s = new string(buffer); // 将字节转为字符 // 去除空格 s = s.trim(); system.out.println(s); } catch(exception e){ system.out.println(e); } } }
6.2. 大文件的读写方法和字符流的使用
1. 大文件读写
import java.io.*; class test{ public static void main(string[] args){ fileinputstream fis = null; fileoutputstream fos = null; try{ fis = new fileinputstream("d:/from.txt"); fos = new fileoutputstream("d:/to.txt"); byte[] buffer = new byte[100]; // 大文件:循环读取 while(true){ int temp = fis.read(buffer, 0, 100); // 读到文件最后的时候,read返回-1 if (temp == -1){ break; } fos.write(buffer,0, temp); } } catch(exception e){ system.out.println(e); } finally{ // 一定要在finally中关闭文件管道 try{ fis.close(); fos.close(); } catch(exception e){ system.out.println(e); } } } }
2.字符流
- 读写文件是,以字符为基础
- 核心方法:
reader(抽象类) <- filereader
,writer(抽象类) <-filwriter
-reader: int read(char[] b, int off, int len)
,返回读取了多少字节的数据
-writer: void write(char[] b, int off, int len)
import java.io.*; class test{ public static void main(string[] args){ filereader fr = null; filwriter fw = null; try{ fr = new filereader("d:/from.txt"); fw = new filewriter("d:/to.txt"); char[] buffer = new char[100]; int temp = fr.read(buffer,0,buffer.length); }catch(exception e){ system.out.println(e); } finally{ // 一定要在finally中关闭文件管道 try{ fr.close(); fw.close(); } catch(exception e){ system.out.println(e); } } } }
6.3. 节点流和处理流
1. 处理流: bufferedreader
:字符输入处理流
-
readline
功能
- 生成bufferedreader对象的方法:
bufferedreader in = new bufferedreader(new filereader("d:/from.txt"))
import java.io.*; class test{ public static void main(string[] args){ filereader filereader = null; bufferedreader bufferedreader = null; try{ filereader = new filereader("d:/from.txt"); bufferedreader = new bufferedreader(filereader); // 按照一行一行的读取 strign line = null; while(true){ line = bufferedreader.readline(); if (line == null){ break; } // 打印每一行 system.out.println(line) } } catch(exception e){ system.out.println(e); } finally{ // 一定要在finally中关闭文件管道 try{ filereader.close(); bufferedreader.close(); } catch(exception e){ system.out.println(e); } } } }
7.内部类和匿名内部类
7.1. 内部类
- 生成内部类的对象:
a.b b = new a().new b();
class a{ int i; // 内部类:a&b.class class b{ int j; int funb(){ // 内部类可以随意使用外部类的变量 int result = i+j; return result; } } } class test{ public static void main(string[] args){ // 生成内部类的对象 a a =new a(); a.b b = new a().new b(); a.i = 3; b.j = 1; b.funb(); // 结果是 3 + 1 = 4; } }
7.2. 匿名内部类
interface a{ public void dosomething{}; } class b{ public void fun(a a){ system.out.println("b lei"); a.dosomething(); } } class test{ public static void main(string[] args){ b b = new b(); // 利用匿名内部类 来继承父类或者实现接口 b.fun(new a(){ public vod dosomething(){ system.out.println("do domething"); } }) } }
上一篇: Java高级教程02