Java高级教程
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高级教程的更多相关文章
- 【Java学习系列】第3课--Java 高级教程
本文地址 可以拜读: 从零开始学 Java 分享提纲: 1. Java数据结构 2. Java 集合框架 3. Java泛型 4. Java序列化 5. Java网络编程 6. Java发送Email ...
- Java高级教程:Java并发性和多线程
Java并发性和多线程: (中文,属于人工翻译,高质量):http://ifeve.com/java-concurrency-thread-directory/ (英文):http://tutoria ...
- Java高级教程02
目录 1.Java线程 1.1. 多线程和多进程 1.2. 线程的执行过程: 1.3. 创建线程的方法 (1). 方法1:通过run() (2). 方法2: 复写Runnable接口(推荐) 1.4. ...
- 这是一套Java菜鸟到大牛的学习路线之高级教程,由工作了10年的资深Java架构师整理。
这是一套Java菜鸟到大牛的学习路线之高级教程,由工作了10年的资深Java架构师整理. 01-java高级架构师设计-基础深入 J2SE深入讲解 Java多 ...
- ios cocopods 安装使用及高级教程
CocoaPods简介 每种语言发展到一个阶段,就会出现相应的依赖管理工具,例如Java语言的Maven,nodejs的npm.随着iOS开发者的增多,业界也出现了为iOS程序提供依赖管理的工具,它的 ...
- 2017最新技术java高级架构、千万高并发、分布式集群、架构师入门到精通视频教程
* { font-family: "Microsoft YaHei" !important } h1 { color: #FF0 } 15套java架构师.集群.高可用.高可扩展. ...
- Java自学教程视频
BAT大咖助力 全面升级Android面试 BAT大牛亲授 基于ElasticSearch的搜房网实战 从天气项目看Spring Cloud微服务治理 Java企业级电商项目架构演进之路 Tomca ...
- java高级精讲之高并发抢红包~揭开Redis分布式集群与Lua神秘面纱
java高级精讲之高并发抢红包~揭开Redis分布式集群与Lua神秘面纱 redis数据库 Redis企业集群高级应用精品教程[图灵学院] Redis权威指南 利用redis + lua解决抢红包高并 ...
- Java基础教程:注解
Java基础教程:注解 本篇文章参考的相关资料链接: 维基百科:https://zh.wikipedia.org/wiki/Java%E6%B3%A8%E8%A7%A3 注解基础与高级应用:http: ...
随机推荐
- MySQL系列详解三:MySQL中各类日志详解-技术流ken
前言 日志文件记录了MySQL数据库的各种类型的活动,MySQL数据库中常见的日志文件有 查询日志,慢查询日志,错误日志,二进制日志,中继日志 .下面分别对他们进行介绍. 查询日志 1.查看查询日志变 ...
- IdentityServer4 中文文档 -12- (快速入门)添加外部认证支持
IdentityServer4 中文文档 -12- (快速入门)添加外部认证支持 原文:http://docs.identityserver.io/en/release/quickstarts/4_e ...
- C# 动态代码生成控件后其他事件不能获取该控件的值
1.新建web项目,添加两个Button控件,结果如图. 2.Button按钮控件点击事件代码如下 protectedvoid Button1_Click(object sender, EventAr ...
- H5 五子棋源码
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content ...
- JAVA & .NET创建对象构造函数调用顺序
JAVA 定义Person类 package models; public class Person { public Person() { System.out.println("pe ...
- mysql写注释的几种方法
MySQL的注释风格总的来说有三种.它们分别是 1.单行注释可以用"#" select 1 as cname; #this is a comment +-------+ | cna ...
- python文件夹copy器(多进程版)
本节的练习的要求如下: 输入要拷贝文件夹的文件名称 读取该文件夹下的所有文件 启动5个进程来拷贝文件夹,将拷贝成功的文件名称放入队列中 主进程中显示文件拷贝的进度 代码如下: import multi ...
- Django之URL路由系统
一 URL配置 Django 1.11版本 URLConf官方文档 URL配置(URLconf)就像Django 所支撑网站的目录.它的本质是URL与要为该URL调用的视图函数之间的映射表.你就是以这 ...
- CSS样式—— 字体、元素的垂直水平居中
1.CSS样式与HTML中标签属性的区别: 标签的属性是采用 属性名=“属性值” 表示的 CSS样式是采用名值对 属性名:属性值: 表示的 2.内联元素(行内元素)与块元素 (1)内联元素及其特点: ...
- SSIS 包部署错误 0xC0010014
SSIS 包部署错误 0xC0010014 Reinhard 在部署 SSIS 包时,提示如下错误. 由于错误 0xC0010014"发生了一个或多个错误.在此消息之前应有更为具体的错误消息 ...