文章目录
- 3、面向对象
- 3.1 介绍
- 3.1.1 基本语法
- 3.1.2 案例分析
- 3.2 类和对象
- 3.2.1 类
- 3.2.1 对象
- 3.3 属性
- 3.4 方法
- 3.5 方法参数
- 3.6 传值方式
- 3.7 静态
- 3.8 静态代码块
- 3.9 包
- 3.10 import
- 3.11 构造方法
- 3.12 继承
- 3.13 super、this
- 3.14 继承、构造方法
- 3.15 多态
- 3.16 方法重载
- 3.17 方法重载小练习
- 3.18 方法重写
- 3.19 方法重写 小练习
- 3.20 递归
- 3.21 访问权限
- 3.22 访问权限 小练习
- 3.23内部类
- 3.24 单例模式
- 3.25 final
- 3.26 抽象
- 3.27 抽象类、抽象方法
- 3.28 接口
- 3.29 枚举
- 3.30 匿名类
- 3.31 bean规范
- 3.32 作用域
Java零基础极速入门-讲师:海波
失败,是正因你在距成功一步之遥的时候停住了脚步。
3、面向对象
面向过程:把问题解决的步骤作为核心来分析,最后解决问题。
面向对象:把问题本身所涉及到事物(Object:对象)为核心分析,最后解决问题。
3.1 介绍
类:归纳和整理。
对象:具体的事物。
3.1.1 基本语法
基本语法结构
class 类名 {
// 特征(属性)
// 功能(方法)
}
问题:做一道菜,红烧排骨
类:菜
对象:红烧排骨
- 步骤1 声明类
- 步骤2 创建对象
- 步骤3 声明属性,所谓属性其实就是类中的变量
- 属性类型 属性名称 = 属性值
- 变量类型 变量名称 = 变量值
- 步骤4 声明方法
- void 方法名(参数){ 功能代码 }
- 步骤5 执行方法
- 对象.属性;
- 对象.方法名();
3.1.2 案例分析
// 步骤1 声明类
class Cooking {
// 特征(属性)
// 名字
String name;
// 菜的类型
String type = "红烧";
// 食材
String food;
// 酌量
String relish = "大料";
}
// 步骤2 创建对象
new Cooking();
// 步骤3 声明属性
// 引用数据类型
Cooking c = new Cooking();
c.name = "红烧排骨";
c.food = "排骨";
//步骤4 声明方法
//void 方法名(参数){ 功能代码 }
class Cooking {
// 特征(属性)
// 名字
String name;
// 菜的类型
String type = "红烧";
// 食材
String food;
// 酌量
String relish = "大料";
// 方法
void execute(){
System.out.println("准备食材" + food);
System.out.println("准备佐料" + relish);
System.out.println("开始烹饪");
System.out.println(name + "烹饪完成");
}
}
// 步骤5 执行方法
Cooking c = new Cooking();
c.name = "红烧排骨";
c.food = "排骨";
c.execute();
// 在创建一个对象
Cooking c = new Cooking();
c.name = "红烧雨";
c.food = "鲫鱼";
c.execute();
3.2 类和对象
3.2.1 类
/*
基本语法:
声明
class 类名 {
// 属性 (0个或多个)
类型 名称 = 值
// 方法 (0个或多个)
void 方法名() {
逻辑代码
}
}
使用
构建对象:new 类名()
访问属性:对象.属性名
访问方法:对象.方法名()
*/
类:结构体,包含了属性(特征)和方法(行为),使用类可以有很多对象。
class:关键字(全是小写)
类名:类的名称,它是标识符,需要最寻规则,一般情况下,类名首字母大写。
3.2.1 对象
对象:类的实例化(具象化)
new:关键字,表示创建一个具体的对象,使用一次,创建一次,每次都是全新。
一般new出来的对象都是赋值给变量,方便重复使用。
变量的类型就是对象的类型。
对象是将内存地址赋值给了变量,变量其实引用了内存中的对象,所以称之为引用变量。
变量的类型称之为引用数据类型。
想要创建对象,new 类 会先到元空间,检查类信息,有的话,就在堆中创建对象,在把堆内存地址给栈中的变量,用户在使用变量,通过变量操作对象。
特殊的对象:空对象,没有引用的对象,称之为空对象,null是关键字对象。
所有引用类型变量的默认取值都是null。
USer user = null;
3.3 属性
属性:每个对象都具有的相同特征。
语法和变量的声明很像。
属性类型 属性名称 = 属性名
如果在声明属性的同时,进行了初始化赋值,那么所有对象的属性就完全相同。
如果希望每个对象的属性不一致,可以不用在声明属性的时候进行初始化。
属性会在构建对象的时候默认初始化,而默认初始化的值取决于属性的类型。
byte、short、int、long = 0
float、double = 0.0
boolean = false
char = 空字符
引用数据类型 = null
变量作用域非常小,只在当前的大括号有效。
属性不仅仅在当前类中有效,可以随着对象在其它的地方使用。
变量使用前必须初始化,否则出现错误,属性可以不用初始化,因为JVM会帮助用户自动完成初始化。
3.4 方法
对象的行为和功能
// 声明的语法:(方法的返回值类型)或(void) 方法名() { 逻辑代码 }
// void:表示方法的结果(返回值),void就是没有结果
// 方法的调用方式:对象.方法名();
// 通过事务共同特性提炼类
// 例:使用用户账号密码进行登录
// 名词:用户、账号、密码
// 动词:登录
// 对象
Usuer user = new User();
// 接受返回值
boolean register = user.register();
// 判断结果
if ( register ) {
System.out.println("注册成功");
boolean loginResult = user.login();
if( loginResult ) {
System.out.println("登录成功");
} else {
System.out.println("登录失败");
}
} else {
System.out.println("注册失败");
}
// 类
class User {
String account;
String password;
/* // 不带返回值
void register(){
System.out.println("用户注册");
}
*/
//带返回值
boolean register(){
System.out.println("用户注册");
return true;
}
/*
// 不带返回值
void login(){
System.out.println("用户登录");
}
*/
// 带返回值
boolean login(){
System.out.println("用户登录");
return false;
}
}
3.5 方法参数
使用外部数据控制方法内部实现的操作,使用的是参数语法实现,也叫方法参数。
public class Demo {
public static void main(String[] args) {
User user = new User();
String name = "zhangsan";
// 传递参数
user.sayHello(name);
// 传递多个参数
user.info("Tom",19,"china");
}
// 可变参数传参
user.test(); // 可以不传
user.test("1","2","3"); // 可以传递多个
}
class User {
// 语法:方法名( 参数类型 参数名称 ),小括号:参数列表
void sayHello( String name ) {
// 使用参数
System.out.println("hello" + name );
}
// 语法:方法名( 参数类型1 参数名称1 ,参数类型2 参数名称2 ,参数类型3 参数名称3)
void info( String name, int age, String address){
// 使用参数
System.out.println("姓名:" + name + ",年龄:" + age + ",地址:" + address);
}
// 当方法传递多个参数时,需要注意:
// 1.参数的个数需要匹配
// 2.参数的类型需要匹配
// 3.参数的顺序需要匹配
// 可变参数
// 特殊情况,参数个数不确定,但是类型都相同
// 语法:参数类型... 参数名称
void test( String... name ) {
System.out.println(name);
}
// 如果还包含其他含义的参数,可变参数必须放到最后
void test01( int age, String... name) {
System.out.println(name);
}
}
3.6 传值方式
例1:基本数据的传递
public class Java07 {
public static void main(String[] args) {
int i = 10;
test(i);
System.out.println(i); // 结果为:10
// 原因是i的作用域范围在{}中,这是两个作用域中的相同名字的两个变量。
}
public static void test(int i) {
i = i + 10;
}
}
main方法中i的作用域范围在{}中,test方法中i的作用域范围在{}中,这是两个作用域中的相同名字的两个变量,当test方法使用完弹栈,打印main方法中i,值没有变化。
例2:引用数据类型,String传递
public class Java07 {
public static void main(String[] args) {
String s = "abc";
test(s);
System.out.println(s); // 结果为:abc
}
public static void test(String s) {
s = s + 10;
}
}
main方法中的s在堆中内存地址传递给test方法中的s,当test方法改变s,就会产生新的字符串对象,test方法中s的内存地址发生变化,但是main中的内存地址没有发生变化,test执行完弹栈,打印main中s,s的值不变。
例3 引用数据类型,类的传递
public class Java07 {
public static void main(String[] args) {
User user = new User();
user.name = "zhangsan";
test(user);
System.out.println(user.name); // 结果为:Tom
}
public static void test(User user) {
user.name = "lisi";
}
}
class User {
String name;
}
在main方法中对User对象中name第一次赋值。
将内存地址传递给test方法中,在test方法中修改User对象name,当test方法执行完,弹栈,执行main方法中打印,打印结果为lisi。
java中方法参数的传递时值传递。
基本数据类型:数值
引用数据类型:引用地址
3.7 静态
针对具体对象的属性称之为对象属性(成员属性、实例属性)
针对具体对象的方法称之为对象方法(成员方法、实例方法)
把和对象无关,只和类相关的称之为静态
和类相关的属性称之为静态属性
和类相关的方法称之为静态方法
静态语法就是在属性和方法前增加static关键字
// 静态属性和静态方法使用
// 类名.属性
// 类名.方法
class Bird{
// 静态属性
static String type = "鸟";
// 静态方法
static void fly() {
System.out.println("飞");
}
}
3.8 静态代码块
栈、堆、元空间(方法去)所存的信息
静态属性、静态方法的存放位置
静态方法和成员方法的关系
现有类,再有对象
成员方法可以访问静态方法、静态属性
静态方法不可以访问成员方法、成员属性
// 静态代码块:类的信息加载完成后,会自动调用静态代码块
// 作用:完成静态属性的初始化功能
// 执行顺序:按照声明顺序自动执行
class User{
// 静态代码块
static {
System.out.println("静态代码块");
}
static void test(){
System.out.println("静态方法");
}
}
// 对象准备创建时,也会自动调用代码块,但不是静态的
// 执行顺序:按照声明顺序自动执行,先执行静态代码块,在执行代码块
class User2{
//代码块
{
System.out.println("代码块");
}
}
3.9 包
为了更好的组织类,java提供了包机制,用于区别类名的命名空间。
// 包名:一般利用公司域名倒置作为包名,全部小写,多个包使用点隔开
// 基本语法:package 包名;
package com.tianyu.dao.User;
// 一个类可以没有包package,但是不可以出现多次
// Java存在不同包的相同名称的类,可以使用包进行区分。
// 一般情况下,在使用类,用户都会使用类的全名(包名+类名)
关于java.lang包,Java虚拟机自动帮助用户添加包名(java.lang),在使用这个包内的类是不用写包名。
3.10 import
Java包+类 书写麻烦,引入import,通过import导入一次,在类中就不需要写包名。
// 位置:在package后面,类的前面写
// import用于在使用类前准备好类
// import关键字可以多次使用,导入多个类
// import在同一个包中导入大量的类,可以使用通配符来简化操作 import java.util.*;
// 如果import不同包中相同名称的类,还是需要在使用时增加包名。
import java.util.Date;
3.11 构造方法
User user = new User();在类名后面写一个小括号,是一种特殊方法调用,指的是调用这个方法之后,对象就会构建出来,所以就把这个方法称之为构造方法。
构建方法:专门用于构建对象。
如果当前的类中没有构造方法,Java虚拟机会自动添加一个公共的、无参的构造方法,方便对象的调用。
// 基本语法 类名(){}
class User{
// 1.构造方法也是方法,但没有Java关键字
// 2.方法名和类名完全相同。
// 3.如果类中没有构造方法,JVM会提供默认的构造方法。
// 4.如果类中有构造方法,JVM不会提供默认的构造方法。
// 5.构造方法也是方法,也可以传递参数,一般传递参数的目的是为了对象属性的赋值。
// 代码块先执行,然后知构造方法
String username;
// 无参构造方法
User(){
System.out.println("无参构造方法");
}
// 有参构造方法
User(String name){
System.out.println("有参构造方法");
username = name;
}
}
3.12 继承
面向对象编程中有3个非常重要的特征:继承、封装、多态。
类存在父子关系:子类可以直接获取父类的成员属性和成员方法。
类的继承只能是单继承,一个类只能有一个父类,不能存在多个父类。
一个父类可以有多个子类。
继承关键字:extends
// 继承采用extends语法:子类 extends 父类
class Parent{
String name = "zhangsan";
void test() {
System.out.println("test");
}
}
class Child extends Parent{
// 继承成功,子类已经拥有父类属性和方法
}
3.13 super、this
super:当前类的父类
this:当前类
这两个关键字在静态代码块和静态方法中,是不可以使用的。
// 继承采用extends语法:子类 extends 父类
class Parent{
String name = "父类";
void test1() {
System.out.println("test");
}
}
class Child extends Parent{
// 继承成功,子类已经拥有父类属性和方法
String name = "子类";
void test2(){
// 当子类和父类名字相同,可以使用super、this区分
System.out.println(this.name); // 当前,当什么都不写默认调用this.name
System.out.println(super.name);// 父类
}
}
3.14 继承、构造方法
class Demo{
public static void main(String[] args){
// 构造方法
Child c1 = new Child();
Child c1 = new Child();
Child c1 = new Child();
// 这里创建几个父类? 父类也创建了3个
// 父类对象是在子类对象创建前创建完成,创建子类对象前,会调用父类的构造方法完成父类的创建
// 默认情况下,子类对象构建时,会默认调用父类的构造方法,使用super的方式,这个过程JVM自动完成
// 如果父类提供了构造方法,JVM就不会提供默认的构造方法,子类就应该显示调用super方法构建父类对象
// new:只会构建一个对象,说new子类,父类也会构建出来,是不准确的,在子类中,并没有父类,有的父类成员属性、成员方法,将它门画在父类圈中是因为它们来自父类,执行父类构造方法是因为,从父类继承过来的属性和方法需要初始化
// 在构造方法执行之前,对象就已经在内存中开辟空间,创建出来了
// 先后顺序:先有对象开辟内存空间,在执行构造方法
// 构造方法的主要目的就是为了完成内存空间属性的初始化操作
}
}
class Parent{
Parent(){
System.out.println("Parent构造方法");
}
}
class Child extends Parent{
Child(){
//super();这个super是JVM自动写的,如果父类中有有参构造,且没有无参构造,需要用户自己写
System.out.println("Child构造方法");
}
}
3.15 多态
一个对象在不同场景下表现出来不同状态和形态
class Demo{
public static void main(String[] args){
// 多态
Person p = new Person();
p.testPerson(); // 可以调用父类方法
Person p1 = new Boy();
p1.testPerson(); // 可以调用父类方法,但是无法调用自己方法
Person p2 = new Gril();
p2.testPerson(); // 可以调用父类方法,但是无法调用自己方法
// 多态语法就是对对象的使用场景进行了约束
// 一个对象可以使用的功能取决于引用变量的类型
}
}
class Parent{
void testPerson(){
System.out.println("test person");
}
}
class Boy extends Parent{
void testBoy(){
System.out.println("test boy");
}
}
class Gril extends Parent{
void testGril(){
System.out.println("test girl");
}
}
3.16 方法重载
class Demo{
public static void main(String[] args){
// 一个类中,不能重复声明相同的方法、属性
// 相同的方法指的是方法名、参数列表相同,与返回值类型无关
// 方法名相同,参数列表(个数、顺序、类型)不相同,会认为是不同的方法,只不过名称一样
// 这个操作在Java称之为重载
User user = new User();
user.login("user","password");
user.login(123123);
user.login("232323");
// 构造方法也存在方法的重载,new User();小括号传什么参数,就用那个构造方法
}
}
class User{
// 构造方法重载
User(){
System.out.println("无参构造");
}
User(String name){
System.out.println("有参构造" + name);
}
// 方法重载
void login( String account, String password){
System.out.println("账号、密码登录");
}
void login( int tel){
System.out.println("手机验证码登录");
}
void login( String wx){
System.out.println("微信、支付宝登录");
}
}
3.17 方法重载小练习
练习1:构造方法的相互调用
class Demo{
public static void main(String[] args){
// 在一个构造方法中,想要调用其他构造方法,需要使用特殊的关键字:this
User user = new User();
}
}
class User{
// 构造方法重载
User(){
this("zhangsan"); // 调用本类其它构造方法
System.out.println("无参构造");
}
User(String name){
this("zhangsan","男"); // 调用本类其它构造方法
System.out.println("有1参构造" + name);
}
User(String name, String sex){
System.out.println("有2参构造" + name + sex);
}
// 方法重载
void login( String account, String password){
System.out.println("账号、密码登录");
}
void login( int tel){
System.out.println("手机验证码登录");
}
void login( String wx){
System.out.println("微信、支付宝登录");
}
}
练习2:当前方法参数没有的数字类型,走那一方法。
class Demo{
public static void main(String[] args){
byte b = 10;
//test(b); //结果bbb
test(b); //结果sss
// 当程序在重载的方法中找不到当前的数字数据类型,就会自动扩大类型
// byte 8位
// short 16位
// char 16位
// int 32位
// 基本数据类型在匹配方法时,可以在数值不变的情况下,扩大数据的精度
// byte类型是无法和char类型做转换,char没有负数,但是byte有负数,只能在提升精度到32位
}
static void test( byte b){
System.out.println("bbb");
}
static void test( short s){
System.out.println("sss");
}
static void test( char c){
System.out.println("ccc");
}
static void test( int i){
System.out.println("iii");
}
}
练习3:引用数据类型
class Demo{
public static void main(String[] args){
// 情况1
//AAA aaa = new AAA();
//test(aaa); // 打印aaa
// 情况2
//BBB aaa = new BBB();
//test(aaa); // 打印bbb
// 情况3
AAA aaa = new BBB();
test(aaa); // 打印aaa
// 多态就是约束了对象的使用场景
// 方法的重载:方法名相同,参数列表不同(个数、顺序、类型)
// 类型:变量的类型就是AAA,类型就是AAA
// 如果AAA方法注释掉了,根本就跑不通,因为使用的场景是AAA
// 引用数据类型不会提升精度,但会提升数据类型,寻找更高一级父类,AAA-->Object,但是Object也没有
}
static void test( AAA aaa){
System.out.println("aaa");
}
static void test( BBB bbb){
System.out.println("bbb");
}
}
class AAA{
}
class BBB extends AAA{
}
3.18 方法重写
在之前父类和子类有相同属性,可以使用this、super区分使用,如果父类和子类有相同方法,该如果使用。
class Demo{
public static void main(String[] args){
Child d = new Child();
d.test();// 运行的是子类方法
// 如果想调用父类中的方法,就在子类方法中写super.test();
// 父类对象的方法主要体现共通性,但不适合一些子类在特殊场合下使用,所以子类需要重写方法的逻辑,这个操作称之为方法的重写
// 重写并不意味父类的方法被覆盖掉,只是当前场合不适用,使用super关键字还是可以调用父类方法
// 方法的重写要求
// 子类方法和父类方法,方法名相同、返回值类型相同、参数列表相同
//构造方法无法重写,因为名字不相同
}
}
class Parent{
String name = "zhangsan";
void test(){
System.out.println("父类同名方法");
}
}
class Child extends Parent{
String name = "lisi";
void test(){
//System.out.println(this.name);
//System.out.println(super.name);
//super.test();//这样就可以调用父类方法
System.out.println("子类同名方法");
}
}
3.19 方法重写 小练习
问题:多态+重写
class Demo{
public static void main(String[] args){
// 方式1
//CCC ccc = new CCC();
//System.out.println(ccc.sum()); 结果:10
// 方式2
//DDD ddd = new DDD();
//System.out.println(ddd.sum()); 结果:40
// 方式3
//CCC ccc = new DDD();
//System.out.println(ccc.sum()); 结果:40
// 一个对象能使用什么方法取决于引用变量的类型
// 一个对象能使用什么属性取决于引用变量的类型
// 一个对象的方法,具体使用(直接或间接调用)是需要看具体对象(new DDD();)
// 一个对象的方法,具体使用是不需要看具体对象,只需要看引用变量类型(CCC ccc)
// 方式4
CCC ccc = new DDD();
System.out.println(ccc.sum()); 结果:30
}
}
class CCC{
int i = 10;
int sum(){
return getI() + 10;
}
int getI(){
return i;
}
}
class DDD extends CCC{
int i = 20;
// int sum(){
// return i + 20;
// }
int getI(){
return i;
}
}
3.20 递归
方法调用自身,称之为递归方法。
class Demo{
public static void main(String[] args){
// 求10以内基数和
// 1 + 3 + 5 + 7 + 9
int result = computeAP(10);
System.out.println(result); // 25
// 阶乘
int result1 = computeFactoryial(5);
System.out.println(result1); // 120
// 1.递归方法有跳出的逻辑(没有跳出逻辑,不断的压栈,栈会溢出,程序报错)
// 2.调用自身时,传递的参数要有规律
}
// 等差数列
static int computeAP(int num){
// num不能位偶数,只能位基数
num = num % 2 == 0 ? num - 1 : num;
// 当num等于1 返回1,并不在循环调用。
if( num == 1){
return 1;
else{
return num + computeAp(num - 2);
}
}
// 阶乘:5!= 5 * 4 * 3 * 2 * 1
// 0的阶乘为1
// 一个大于1的数的阶乘等于这个数诚意这个数减一的阶乘
static int computeFactoryial(int num){
if( num <= 1){
return 1;
}else{
num * computeFactoryial(num - 1);
}
}
}
3.21 访问权限
public class Demo{
public static void main(String[] args){
// public:公共的,访问权限修饰符
// java的源码中,公共类只能有一个,而且必须和源码文件名相同
// main方法:是由JVM调用的,JVM调用时应该可以任意调用,而不用考虑权限
// java中访问权限主要分4种
// 1.private:私有的(同一个类中可以使用)
// 2.(default):默认权限(当不设定任何权限时,JVM会默认提供权限,包(路径)权限,必须是相同的包路径)
// 3.protected:受保护的权限,子类可以访问(同一个类、同一个包都可以访问)🙋
// 4.public:公共的(任意使用)
// JVM默认给类提供的构造方法,就是公共的、无参构造方法
}
}
3.22 访问权限 小练习
public class Demo{
public static void main(String[] args){
Person p = new Person();
// private:同类
// default:同类、同包(路径)
// protected:同类、同包(路径)、子类
// public:公共的
// 访问权限,就是访问属性、方法的权力和限制
// 访问谁?Demo 它的父类-> super ->java.lang.Object
// 谁访问?Person 它的父类-> super -> java.lang.Object 中 clone方法
p.clone();//不能被访问
}
}
class Person(){
// 只有在Person中可以使用clone方法
}
3.23内部类
public class Demo{
public static void main(String[] args){
// Java不允许使用private、protected修饰外部类
// 外部类,就是在源码中直接声明的类
// 内部类,类中声明的类
// 内部类就当成外部类属性使用即可
// 因为内部类可以看作外部类的属性,所以需要构建外部类对象才可以使用
// 使用方式
OuterClass outer = new OuterClass();
OuterClass.InnerClass innerClass = outer.new InnerClass();
}
}
class OuterClass {
// 内部类声明:有时候为了一些特殊的数据,可以在类中在声明一个类
class InnerClass{
}
}
3.24 单例模式
将类的构造方法私有,通过执行静态方法获取类对象
public class Demo{
public static void main(String[] args){
// 类的构造方法使用private
// 1.类的创建过程复杂
// 2.类的对象消耗资源
User u1 = User.getInstance();
User u2 = User.getInstance();
User u3 = User.getInstance();
User u4 = User.getInstance();
if( u1 == u2){
System.out.println("相同");
}else{
System.out.println("相同");
}
}
}
class User{
private static User user = null;
private User(){
}
public static User getInstance(){
// 判断类只能被创建一次
if( user == null ){
user = new User();
}
return user;
}
}
3.25 final
属性值不想被修改,可以使用final关键字修饰
public class Demo{
public static void main(String[] args){
// Java提供了一种语法,可以在数据初始化之后不被修改,使用关键字final
// final可以修饰变量:变量的值一旦初始化后无法修改
// final可以修饰属性:修饰属性后JVM无法自动进行初始化,需要自己手动初始化,属性值不能发生变化
// 一般将final修饰的变量称之为常量,或者叫不可变变量
final String name = "zhangsan";
// final可以修饰方法,修饰后不可以被子类重写
// final可以修饰类,修饰后不可以被继承
// final不可以修饰构造方法
// final可以修饰方法参数,一旦修饰,参数无法修改
}
}
final class User{
private final String name;
// 通过构造方法对属性初始化
public User(String name){
this.name = name;
}
public final void test(){
}
}
class child extends User{
// 子类无法重写
//public void test(){
//}
}
3.26 抽象
抽象:模糊具体的功能,先从整体入手做布局和设计,把整体布局和设计做完,在设计具体功能。
public class Demo{
public static void main(String[] args){
// 抽象 Abstract
// 抽象类
// 抽象方法
// 面向对象的学习中,用户是先有对象,通过分析对象提炼出类
// 分析问题:对象(具体的)=> 类(抽象的)
// 编写代码:类(抽象的)=> 对象(具体的)
}
}
3.27 抽象类、抽象方法
public class Demo{
public static void main(String[] args){
// 不完整的类就是抽象类(因为抽象类不完整,所以抽象类无法直接构建对象)
// abstract class 类名
// 抽象方法:只有声明没有实现
// abstract 返回值类型 方法名(参数);
// 如果一个类中有抽象方法,这个类一定是抽象类
// 如果一个类是抽象类,它的方法不一定是抽象方法
// 抽象类无法直接构建对象,可以通过子类间接构建对象
// 抽象类中有抽象方法,子类继承抽象类,需要重写抽象方法,将方法补充完整
// abstract关键字不可以与final同时使用
}
}
// 抽象类
abstract class Person{
// 抽象方法
public abstract void eat();
// 正常方法
public void test(){
}
}
// 想要使用抽象类,只能通过子类继承
class Chinese extends Person{
public void eat(){
System.out.println("中国人使用筷子吃饭");
}
}
3.28 接口
public class Demo{
public static void main(String[] args){
// 接口:可以简单理解为规则
// 基本语法:interface 接口名称{规则属性,规则的行为}
// 接口其实是抽象的
// 规则的属性必须为固定值,且不能修改
// 属性和行为的访问权限必须是公共的
// 属性应该是静态的
// 应为应该是抽象的
// 接口和类是两个层面的东西
// 类的对象需要最寻接口,在java中,这个遵循,称之为实现(implements),类需要实现接口,而且可以实现多个接口
Computer c = new Computer();
Light light = new Light();
c.usb1 = light;
Light light1 = new Light();
c.usb2 = light1;
c.powerSupply();
}
}
// USB接口规范
interface USBInterface {
}
// USB供电功能
interface USBSupply extends USBInterface {
public void powerSupply();
}
// USB链接功能
interface USBReceive extends USBInterface {
public void powerReceive();
}
// 电脑
class Computer implements USBSupply {
public USBReceive usb1;
public USBReceive usb2;
public void powerSupply(){
System.out.println("USB接口提供电源");
usb1.powerReceive();
usb2.powerReceive();
}
}
// 台灯
class Light implements USBReceive {
public void powerReceive(){
System.out.println("开始给台灯供电");
}
}
3.29 枚举
public class Demo{
public static void main(String[] args){
// 枚举是一个特殊的类,包含了一组特定的对象,这些对象不会发生改变(不会发生改变的标识符都用大写)
// 枚举使用enum关键字使用
// 使用
System.out.println(City.BEIJING.name);
System.out.println(City.SHANGHAI.name);
// 枚举类不能创建对象,它的对象实在内部自行创建
// 自定义枚举类调用
System.out.println(MyCity.BEIJING.name);
System.out.println(MyCity.SHANGHAI.name);
}
}
// JVM会自动把加了enum的类,继承Enum类
enum City{
// 枚举类会将对象放置在最前面,那么和后面的语法需要使用分号隔开
BEIJING("北京",1001),
SHANGHAI("上海",1002);
City( String name, int code){
this.code = code;
this.name = name;
}
public String name;
public int code;
}
// 不借助JVM,手动写枚举类
class MyCity {
public String name;
public int code;
private MyCity( String name, int code){
this.code = code;
this.name = name;
}
public static final MyCity BEIJING = new MyCity("北京",1001);
public static final MyCity SHANGHAI = new MyCity("上海",1002);
}
3.30 匿名类
public class Demo {
public static void main(String[] args) {
// 在某些场合下,类的名字不重要,用户指使用类中的方法或功能,此时用户可以采用特殊的语法:匿名类
// 匿名类:没有名字的类
Me me = new Me();
me.sayHello(new Person() {
@Override
public String name() {
return "王五";
}
});
// 接口也是可以使用这种方式
new Fly() {
@Override
public void fly() {
System.out.println("使用飞行器飞行");
}
}.fly();
}
}
// 演示接口
interface Fly {
public void fly();
}
// 演示抽象类
abstract class Person {
public abstract String name();
}
class Me {
public void sayHello(Person person) {
System.out.println("hello:" + person.name());
}
}
3.31 bean规范
public class Demo {
public static void main(String[] args) {
// Java中类分两种
// 1.主要用于编写逻辑
// 2.主要用于建立数据模型(Bean)
// Bean类的设计规范:Bean规范
// 1.类要求必须含有无参,公共的构造方法
// 2.属性必须私有化,然后提取公共的set、get方法
User user = new User();
user.setAccount("admin");
user.setPassword("admin");
login(user);
}
public static boolean login(User user) {
if (user.getAccount().equals("admin") && user.getPassword().equals("admin")) {
return true;
} else {
return false;
}
}
}
// 数据模型(bean)
class User {
private String account;
private String password;
public String getAccount() {
return account;
}
public void setAccount(String account) {
this.account = account;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
3.32 作用域
public class Demo {
public static void main(String[] args) {
User user = new User();
user.test();
}
}
class Person {
public String name = "zhangsan";
}
class User extends Person {
public String name = "lisi";
public void test() {
String name = "wangwu";
// 如果属性和(局部)变量的名称相同,访问时不加修饰符,优先访问变量
System.out.println(super.name);// 父类
System.out.println(this.name);// 子类(子类即使不写this,也默认加)
// 如果父类和子类都是静态属性,且同名,在子类静态方法中访问父类
// 直接使用父类.属性 即可(不可以使用super或this)
}
}