目录
一,面向对象的初步认识
1.什么是面向对象
Java是一门纯面向对象的语言(Object Oriented Program,简称OOP),在面向对象的世界里,一切皆为对象。面向对象是解决问题的一种思想,主要依靠对象之间的交互完成一件事情。用面向对象的思想来涉及程序,更符合人们对事物的认知,对于大型程序的设计、扩展以及维护都非常友好。
2.面向对象和面向过程
i.传统洗衣服的过程
传统的方式:注重的是洗衣服的过程,少了一个环节可能都不行。
而且不同衣服洗的方式,时间长度,拧干方式都不同,处理起来就比较麻烦。如果将来要洗鞋子,那就是另一种放方式。
按照该种方式来写代码,将来扩展或者维护起来会比较麻烦
ii.如今洗衣服的过程
以面向对象方式来进行处理,就不关注洗衣服的过程,具体洗衣机是怎么来洗衣服,如何来甩干的,用户不用去关心,只需要将衣服放进洗衣机,倒入洗衣粉,启动开关即可,通过对象之间的交互来完成的。
注意:面向过程和面相对象并不是一门语言,而是解决问题的方法,没有那个好坏之分,都有其专门的应用场景。
二,类的定义和使用
面相对象程序设计关注的是对象,而对象是现实生活中的实体,比如:洗衣机。但是洗衣机计算机并不认识,需要开发人员告诉给计算机什么是洗衣机。
上图左侧就是对洗衣机简单的描述,该过程称为对洗衣机对象(实体)进行抽象(对一个复杂事物的重新认知),但是这些简化的抽象结果计算机也不能识别,开发人员可以采用某种面相对象的编程语言来进行描述,比如:Java语言。
1.简单认识类
类是用来对一个实体(对象)来进行描述的,主要描述该实体(对象)具有哪些属性(外观尺寸等),哪些功能(用来干啥),描述完成后计算机就可以识别了。
比如:洗衣机,它是一个品牌,在 Java 中可以将其看成是一个类别。属性:产品品牌,型号,产品重量,外观尺寸,颜色 ...功能:洗衣,烘干、定时 ....
2.类的定义格式
// 创建类class ClassName {fifield ; // 字段 ( 属性 ) 或者 成员变量method ; // 行为 或者 成员方法}
class WashMachine {public String brand ; // 品牌public String type ; // 型号public double weight ; // 重量public double length ; // 长public double width ; // 宽public double height ; // 高public String color ; // 颜色public void washClothes (){ // 洗衣服System . out . println ( " 洗衣功能 " );}public void dryClothes (){ // 脱水System . out . println ( " 脱水功能 " );}public void setTime (){ // 定时System . out . println ( " 定时功能 " );}
3.定义类练习
i.定义一个狗类
class PetDog {public String name ; // 名字public String color ; // 颜色// 狗的属性public void barks () {System . out . println ( name + ": 旺旺旺 ~~~" );}// 狗的行为public void wag () {System . out . println ( name + ": 摇尾巴 ~~~" );}}
ii.定义一个学生类
public class Student {public String name ;public String gender ;public short age ;public double score ;public void DoClass (){}public void DoHomework (){}public void Exam (){}}
三,类的实例化
1.什么是实例化?
![](https://img-blog.csdnimg.cn/eac8685abe104a20a8a6c412f5391edd.png)
public class Main {public static void main ( String [] args ) {PetDog dogh = new PetDog (); // 通过 new 实例化对象dogh . name = " 阿黄 " ;dogh . color = " 黑黄 " ;dogh . barks ();dogh . wag ();PetDog dogs = new PetDog ();dogs . name = " 阿黄 " ;dogs . color = " 黑黄 " ;dogs . barks ();dogs . wag ();}}输出结果:阿黄 : 旺旺旺 ~~~阿黄 : 摇尾巴 ~~~赛虎 : 旺旺旺 ~~~赛虎 : 摇尾巴 ~~~
![](https://img-blog.csdnimg.cn/fc137545126e4704bd6fe774bbbf29c8.png)
四,this引用
1.为什么会存在this引用
public class Date {public int year ;public int month ;public int day ;public void setDay ( int y , int m , int d ){year = y ;month = m ;day = d ;}public void printDate (){System . out . println ( year + "/" + month + "/" + day );}public static void main ( String [] args ) {// 构造三个日期类型的对象 d1 d2 d3Date d1 = new Date ();Date d2 = new Date ();Date d3 = new Date ();// 对 d1 , d2 , d3 的日期设置d1 . setDay ( 2020 , 9 , 15 );d2 . setDay ( 2020 , 9 , 16 );d3 . setDay ( 2020 , 9 , 17 );// 打印日期中的内容d1 . printDate ();d2 . printDate ();d3 . printDate ();}}
public void setDay ( int year , int month , int day ){year = year ;month = month ;day = day ;}
![](https://img-blog.csdnimg.cn/b4c98d255e884ee9ab9b7d10f36c759a.png)
2.什么是this引用?
public class Date {public int year ;public int month ;public int day ;public void setDay ( int year , int month , int day ){this . year = year ;this . month = month ;this . day = day ;}public void printDate (){System . out . println ( this . year + "/" + this . month + "/" + this . day );}}
public static void main ( StriDate d = new Date ();d . setDay ( 2020 , 9 , 15 );d . printDate ();}
![](https://img-blog.csdnimg.cn/05690162157f427e8b468120d2585045.png)
3.this引用的特性
![](https://img-blog.csdnimg.cn/e137c57d997f4d23b2012d83d8bb38d9.png)
五,对象的构造及初始化
1.如何初始化对象?
public static void main ( String [] args ) {int a ;System . out . println ( a );}// Error:(26, 28) java: 可能尚未初始化变量 a
public static void main ( String [] args ) {Date d = new Date ();d . printDate ();d . setDate ( 2021 , 6 , 9 );d . printDate ();}// 代码可以正常通过编译
2.构造方法
2.1 概念
public class Date {public int year ;public int month ;public int day ;// 构造方法:// 名字与类名相同,没有返回值类型,设置为 void 也不行// 一般情况下使用 public 修饰// 在创建对象时由编译器自动调用,并且在对象的生命周期内只调用一次public Date ( int year , int month , int day ){this . year = year ;this . month = month ;this . day = day ;System . out . println ( "Date(int,int,int) 方法被调用了 " );}public void printDate (){System . out . println ( year + "-" + month + "-" + day );}public static void main ( String [] args ) {// 此处创建了一个 Date 类型的对象,并没有显式调用构造方法Date d = new Date ( 2021 , 6 , 9 ); // 输出 Date(int,int,int) 方法被调用了d . printDate (); // 2021-6-9}}
2.2 特性
public class Date {public int year ;public int month ;public int day ;// 无参构造方法public Date (){this . year = 1900 ;this . month = 1 ;this . day = 1 ;}
// 带有三个参数的构造方法public Date ( int year , int month , int day ) {this . year = year ;this . month = month ;this . day = day ;}public void printDate (){System . out . println ( year + "-" + month + "-" + day );}public static void main ( String [] args ) {Date d = new Date ();d . printDate ();}}
public class Date {public int year ;public int month ;public int day ;public void printDate (){System . out . println ( year + "-" + month + "-" + day );}public static void main ( String [] args ) {Date d = new Date ();d . printDate ();}}
public class Date {public int year ;public int month ;public int day ;public Date ( int year , int month , int day ) {this . year = year ;this . month = month ;this . day = day ;}
public void printDate (){System . out . println ( year + "-" + month + "-" + day );}public static void main ( String [] args ) {// 如果编译器会生成,则生成的构造方法一定是无参的// 则此处创建对象是可以通过编译的// 但实际情况是:编译期报错Date d = new Date ();d . printDate ();}}/*Error:(26, 18) java: 无法将类 extend01.Date 中的构造器 Date 应用到给定类型 ;需要 : int,int,int找到 : 没有参数原因 : 实际参数列表和形式参数列表长度不同*/
public class Date {public int year ;public int month ;public int day ;// 无参构造方法 -- 内部给各个成员赋值初始值,该部分功能与三个参数的构造方法重复// 此处可以在无参构造方法中通过 this 调用带有三个参数的构造方法// 但是 this(1900,1,1); 必须是构造方法中第一条语句public Date (){//System.out.println(year); 注释取消掉,编译会失败this ( 1900 , 1 , 1 );//this.year = 1900;//this.month = 1;//this.day = 1;}// 带有三个参数的构造方法public Date ( int year , int month , int day ) {this . year = year ;this . month = month ;this . day = day ;}}
public Date (){this ( 1900 , 1 , 1 );}public Date ( int year , int month , int day ) {this ();}/*无参构造器调用三个参数的构造器,而三个参数构造器有调用无参的构造器,形成构造器的递归调用编译报错: Error:(19, 12) java: 递归构造器调用*/
3.默认初始化
public class Date {public int year ;public int month ;public int day ;public Date ( int year , int month , int day ) {// 成员变量在定义时,并没有给初始值 , 为什么就可以使用呢?System . out . println ( this . year );System . out . println ( this . month );System . out . println ( this . day );}public static void main ( String [] args ) {// 此处 a 没有初始化,编译时报错:// Error:(24, 28) java: 可能尚未初始化变量 a// int a;// System.out.println(a);Date d = new Date ( 2021 , 6 , 9 );}}
![](https://img-blog.csdnimg.cn/d60ecb6954814b4aa50096a8ab19b4f9.png)
Date d = new Date ( 2021 , 6 , 9 );
数据类型 | 默认值 |
byte | 0 |
char |
'\u0000'
|
short | 0 |
int | 0 |
long | 0L |
boolean |
false
|
float | 0.0f |
double | 0.0 |
reference | null |
4.就地初始化
public class Date {public int year = 1900 ;public int month = 1 ;public int day = 1 ;public Date (){}public Date ( int year , int month , int day ) {}public static void main ( String [] args ) {Date d1 = new Date ( 2021 , 6 , 9 );Date d2 = new Date ();}}
六,封装
1.封装的概念
![](https://img-blog.csdnimg.cn/a972d6d01d5e48489d5ecb0d9b73c821.png)
2.访问限定符
public class Computer {
private String cpu; // cpu
private String memory; // 内存
public String screen; // 屏幕
String brand; // 品牌---->default属性
public Computer(String brand, String cpu, String memory, String screen) {
this.brand = brand;
this.cpu = cpu;
this.memory = memory;
this.screen = screen;
}
public void Boot(){
System.out.println("开机~~~");
}
public void PowerOffff(){
System.out.println("关机~~~");
}
public void SurfInternet(){
System.out.println("上网~~~");
}
}
public class TestComputer {
public static void main(String[] args) {
Computer p = new Computer("HW", "i7", "8G", "13*14");
System.out.println(p.brand); // default属性:只能被本包中类访问
System.out.println(p.screen); // public属性: 可以任何其他类访问
// System.out.println(p.cpu); // private属性:只能在Computer类中访问,不能被其他类访问
}
}
3.封装扩展包
3.1 包的概念
![](https://img-blog.csdnimg.cn/cd0e04e47f0544c59c0835a5b49cc917.png)
3.2 导入包中的类
public class Test {public static void main ( String [] args ) {java . util . Date date = new java . util . Date ();// 得到一个毫秒级别的时间戳System . out . println ( date . getTime ());}}
import java . util . Date ;public class Test {public static void main ( String [] args ) {Date date = new Date ();// 得到一个毫秒级别的时间戳System . out . println ( date . getTime ());}}
import java . util . * ;public class Test {public static void main ( String [] args ) {Date date = new Date ();// 得到一个毫秒级别的时间戳System . out . println ( date . getTime ());}}
import java . util . * ;import java . sql . * ;public class Test {public static void main ( String [] args ) {// util 和 sql 中都存在一个 Date 这样的类 , 此时就会出现歧义 , 编译出错Date date = new Date ();System . out . println ( date . getTime ());}}// 编译出错Error :( 5 , 9 ) java : 对 Date 的引用不明确java . sql 中的类 java . sql . Date 和 java . util 中的类 java . util . Date 都匹配
import java . util . * ;import java . sql . * ;public class Test {public static void main ( String [] args ) {java . util . Date date = new java . util . Date ();System . out . println ( date . getTime ());}}
import static java . lang . Math . * ;public class Test {public static void main ( String [] args ) {double x = 30 ;double y = 40 ;// 静态导入的方式写起来更方便一些 .// double result = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));double result = sqrt ( pow ( x , 2 ) + pow ( y , 2 ));System . out . println ( result );}}
3.3 自定义包
![](https://img-blog.csdnimg.cn/67653d91d19e479ebf4006778e25ba1b.png)
![](https://img-blog.csdnimg.cn/7cced054f54041b28a9a61f6ff989411.png)
![](https://img-blog.csdnimg.cn/bd3117fb0e8d48cd931f1924d96a7ec5.png)
![](https://img-blog.csdnimg.cn/619aa50d6b9c4c8db79bf5b5ed279625.png)
![](https://img-blog.csdnimg.cn/7039493abb6f4b6aa68b3d0ce1aa7da1.png)
3.4 包的访问权限控制举例
package com.bit.demo1;
public class Computer {
private String cpu; // cpu
private String memory; // 内存
public String screen; // 屏幕
String brand; // 品牌
public Computer(String brand, String cpu, String memory, String screen) {
this.brand = brand;
this.cpu = cpu;
this.memory = memory;
this.screen = screen;
}
public void Boot(){
System.out.println("开机~~~");
}
public void PowerOffff(){
System.out.println("关机~~~");
}
public void SurfInternet(){
System.out.println("上网~~~");
}
}
///
package com.bite.demo2;
import com.bite.demo1.Computer;
public class TestComputer {
public static void main(String[] args) {
Computer p = new Computer("HW", "i7", "8G", "13*14");
System.out.println(p.screen);
// System.out.println(p.cpu); // 报错:cup是私有的,不允许被其他类访问
// System.out.println(p.brand); // 报错:brand是default,不允许被其他包中的类访问
}
}
// 注意:如果去掉Computer类之前的public修饰符,代码也会编译失败
3.5 常见的包
七,static成员
1.再谈学生类
public class Student {// ...public static void main ( String [] args ) {Student s1 = new Student ( "Li leilei" , " 男 " , 18 , 3.8 );Student s2 = new Student ( "Han MeiMei" , " 女 " , 19 , 4.0 );Student s3 = new Student ( "Jim" , " 男 " , 18 , 2.6 );}}
![](https://img-blog.csdnimg.cn/93d47e05884642bfb60aa54312272383.png)
2.static修饰成员变量
public class Student{
public String name;
public String gender;
public int age;
public double score;
public static String classRoom = "Bit306";
// ...
public static void main(String[] args) {
// 静态成员变量可以直接通过类名访问
System.out.println(Student.classRoom);
Student s1 = new Student("Li leilei", "男", 18, 3.8);
Student s2 = new Student("Han MeiMei", "女", 19, 4.0);
Student s3 = new Student("Jim", "男", 18, 2.6);
// 也可以通过对象访问:但是classRoom是三个对象共享的
System.out.println(s1.classRoom);
System.out.println(s2.classRoom);
System.out.println(s3.classRoom);
}
}
同学以调试方式运行上述代码,然后在监视窗口中可以看到,静态成员变量并没有存储到某个具体的对象中。
3.stati修饰成员的方法
public class Student {private String name ;private String gender ;private int age ;private double score ;private static String classRoom = "Bit306" ;// ...}public class TestStudent {public static void main ( String [] args ) {System . out . println ( Student . classRoom );}}编译失败:Error :( 10 , 35 ) java : classRoom 在 extend01 . Student 中是 private 访问控制
public class Student{
// ...
private static String classRoom = "Bit306";
// ...
public static String getClassRoom(){
return classRoom;
}
}
public class TestStudent {
public static void main(String[] args) {
System.out.println(Student.getClassRoom());
}
}
输出:Bit306
public static String getClassRoom(){
System.out.println(this);
return classRoom;
}
// 编译失败:Error:(35, 28) java: 无法从静态上下文中引用非静态 变量 this
public static String getClassRoom(){
age += 1;
return classRoom;
}
// 编译失败:Error:(35, 9) java: 无法从静态上下文中引用非静态 变量 age
4. 静态方法中不能调用任何非静态方法,因为非静态方法有this参数,在静态方法中调用时候无法传递this引用
public static String getClassRoom(){
doClass();
return classRoom;
}
// 编译报错:Error:(35, 9) java: 无法从静态上下文中引用非静态 方法 doClass()
5. 静态方法无法重写,不能用来实现多态(此处大家暂时不用管,后序多态位置详细讲解)。
4.static成员变量初始化
public class Student{
private String name;
private String gender;
private int age;
private double score;
private static String classRoom = "Bit306";
// ...
}
八,代码块
1.代码块概念以及分类
2.普通代码块
普通代码块:定义在方法中的代码块.
public class Main {public static void main ( String [] args ) {{ // 直接使用 {} 定义,普通方法块int x = 10 ;System . out . println ( "x1 = " + x );}int x = 100 ;System . out . println ( "x2 = " + x );}}// 执行结果x1 = 10x2 = 100
3.构造代码块
构造块:定义在类中的代码块(不加修饰符)。也叫:实例代码块。构造代码块一般用于初始化实例成员变量。
public class Student{
//实例成员变量
private String name;
private String gender;
private int age;
private double score;
public Student() {
System.out.println("I am Student init()!");
}
//实例代码块
{
this.name = "bit";
this.age = 12;
this.sex = "man";
System.out.println("I am instance init()!");
}
public void show(){
System.out.println("name: "+name+" age: "+age+" sex: "+sex);
}
}
public class Main {
public static void main(String[] args) {
Student stu = new Student();
stu.show();
}
}
// 运行结果
I am instance init()!
I am Student init()!
name: bit age: 12 sex: man
4.静态代码块
使用static定义的代码块称为静态代码块。一般用于初始化静态成员变量。
public class Student{
private String name;
private String gender;
private int age;
private double score;
private static String classRoom;
//实例代码块
{
this.name = "bit";
this.age = 12;
this.gender = "man";
System.out.println("I am instance init()!");
}
// 静态代码块
static {
classRoom = "bit306";
System.out.println("I am static init()!");
}
public Student(){
System.out.println("I am Student init()!");
}
public static void main(String[] args) {
Student s1 = new Student();
Student s2 = new Student();
}
}
九,内部类
public class OutClass {
class InnerClass{
}
}
// OutClass是外部类
// InnerClass是内部类
【注意事项】1. 定义在 class 类名 {} 花括号外部的,即使是在一个文件里,都不能称为内部类
public class A{
}
class B{
}
// A 和 B是两个独立的类,彼此之前没有关系
2. 内部类和外部类共用同一个java源文件,但是经过编译之后,内部类会形成单独的字节码文件
1.内部类的分类
先来看下,内部类都可以在一个类的那些位置进行定义
public class OutClass {
// 成员位置定义:未被static修饰 --->实例内部类
public class InnerClass1{
}
// 成员位置定义:被static修饰 ---> 静态内部类
static class InnerClass2{
}
public void method(){
// 方法中也可以定义内部类 ---> 局部内部类:几乎不用
class InnerClass5{
}
}
}
1.1 内部类
在外部类中,内部类定义位置与外部类成员所处的位置相同,因此称为成员内部类。
1.1.1 内部类实例
public class OutClass {
private int a;
static int b;
int c;
public void methodA(){
a = 10;
System.out.println(a);
}
public static void methodB(){
System.out.println(b);
}
// 实例内部类:未被static修饰
class InnerClass{
int c;
public void methodInner(){
// 在实例内部类中可以直接访问外部类中:任意访问限定符修饰的成员
a = 100;
b =200;
methodA();
methodB();
// 如果外部类和实例内部类中具有相同名称成员时,优先访问的是内部类自己的
c = 300;
System.out.println(c);
// 如果要访问外部类同名成员时候,必须:外部类名称.this.同名成员名字
OutClass.this.c = 400;
System.out.println(OutClass.this.c);
}
}
public static void main(String[] args) {
// 外部类:对象创建 以及 成员访问
OutClass outClass = new OutClass();
System.out.println(outClass.a);
System.out.println(OutClass.b);
System.out.println(outClass.c);
outClass.methodA();
outClass.methodB();
System.out.println("=============实例内部类的访问=============");
// 要访问实例内部类中成员,必须要创建实例内部类的对象
// 而普通内部类定义与外部类成员定义位置相同,因此创建实例内部类对象时必须借助外部类
// 创建实例内部类对象
OutClass.InnerClass innerClass1 = new OutClass().new InnerClass();
// 上述语法比较怪异,也可以先将外部类对象先创建出来,然后再创建实例内部类对象
OutClass.InnerClass innerClass2 = outClass.new InnerClass();
innerClass2.methodInner();
}
}
1.1.2 静态内部类
public class OutClass {
private int a;
static int b;
public void methodA(){
a = 10;
System.out.println(a);
}
public static void methodB(){
System.out.println(b);
}
// 静态内部类:被static修饰的成员内部类
static class InnerClass{
public void methodInner(){
// 在内部类中只能访问外部类的静态成员
// a = 100; // 编译失败,因为a不是类成员变量
b =200;
// methodA(); // 编译失败,因为methodB()不是类成员方法
methodB();
}
}
public static void main(String[] args) {
// 静态内部类对象创建 & 成员访问
OutClass.InnerClass innerClass = new OutClass.InnerClass();
innerClass.methodInner();
}
}
2.局部内部类
public class OutClass {
int a = 10;
public void method(){
int b = 10;
// 局部内部类:定义在方法体内部
// 不能被public、static等访问限定符修饰
class InnerClass{
public void methodInnerClass(){
System.out.println(a);
System.out.println(b);
}
}
// 只能在该方法体内部使用,其他位置都不能用
InnerClass innerClass = new InnerClass();
innerClass.methodInnerClass();
}
public static void main(String[] args) {
// OutClass.InnerClass innerClass = null; 编译失败
}
}
3.匿名内部类
后序讲抽象类和接口时给大家详细介绍。
十,对象的打印
public class Person {
String name;
String gender;
int age;
public Person(String name, String gender, int age) {
this.name = name;
this.gender = gender;
this.age = age;
}
public static void main(String[] args) {
Person person = new Person("Jim","男", 18);
System.out.println(person);
}
}
// 打印结果:day20210829.Person@1b6d3586
如果想要默认打印对象中的属性该如何处理呢?答案:重写toString方法即可。
public class Person {
String name;
String gender;
int age;
public Person(String name, String gender, int age) {
this.name = name;
this.gender = gender;
this.age = age;
}
@Override
public String toString() {
return "[" + name + "," + gender + "," + age + "]";
}
public static void main(String[] args) {
Person person = new Person("Jim","男", 18);
System.out.println(person);
}
}
// 输出结果:[Jim,男,18]
完。