1.面向对象的三大特性
2.封装(面向对象)
提出问题
在开发过程中,如何保证成员变量的安全性问题?
package com.uplooking.demo03;
public class Person {
String name;
int age;
void say() {
System.out.println("my name is " + name + ";my age is " + age);
}
}
package com.uplooking.demo03;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Person p1 = new Person();
System.out.println("请输入用户的名称?");
String name = new Scanner(System.in).next();
System.out.println("请输入用户的年龄?");
int age = new Scanner(System.in).nextInt();
p1.name = name;
p1.age = age;
p1.say();
}
}
属性安全性保证
我们可以把属性 藏
起来,我们就能想到使用访问控制
使用private来修饰我们需要保证安全的属性
package com.uplooking.demo03;
public class Person {
String name;
//使用private修饰,保证属性的安全性
private int age;
void say() {
System.out.println("my name is " + name + ";my age is " + age);
}
/**
* 对外提供的setter方法,来进行属性的赋值
* @param age
*/
public void setAge(int age) {
if (age > 0 && age < 100) {
this.age = age;
}else{
System.out.println("年龄不合法!");
}
}
/**
* 对外提供getter方法,来获取属性
* @return
*/
public int getAge() {
return this.age;
}
}
**为了代码的安全性,把尽可能多的属性给隐藏起来,不让外边随意去访问,要想访问,通过对象调用他们各自的方法,这就是封装的意义所在
封装特性就是利用java中的访问修饰符来完成的;
类
,称为javaBean3.继承(面向对象)
-继承就是子类继承父类(超类|基类)的属性和方法
-java中只支持单继承
-继承的目的
-减少代码块的重复
-使得程序具有更高的可读性,易扩展性
-继承特性的使用
我们创建三个类:
发现存在问题: 有大量的重复代码出现了
改良代码:使用面向对象的继承特性来进行改良
首先创建一个父类: Person
,把公共的成员抽取在父类中,让其他子类继承父类
-访问修饰符
访问修饰符: 控制访问权限的
级别 | public | protected | 默认 | private |
---|---|---|---|---|
类 | yes | yes | yes | yes |
子类 | yes | yes | yes | no |
包 | yes | yes | yes | no |
其他包 | yes | no | no | no |
public和默认
:可以修饰类,成员(成员变量+成员方法)
protected private
:只能修饰成员变量和成员方法总结:
- public: 在任何地方都能访问
- protected: 只在不同的包不能访问
- 默认:只在不同的包不能访问
- private:只在本类中可以访问
- **protected的访问权限大于默认的
一丢丢
,protected在不同包的子类使用super
关键字可以访问
-static关键字
- static不能修饰类
- static可以修饰成员变量和成员方法
- static修饰的成员,不建议使用对象来调用,一般使用类名来调用
- static修饰的成员全局共用一份
- static不能与this进行联合使用
- static修饰的方法中不能使用普通的成员变量,要想使用必须把成员变量声明为
static
修饰的成员变量
static的常用地方: 如果我想一个类的所有对象,想共用同一个变量,则可以使用static修饰,
一处改变,到处随着改变
-java中的final关键字
可以修饰类,成员变量,成员方法
final修饰成员变量时成员变量必须赋值,
- final修饰的变量称为常量
- 常量的名字建议全部大写
- final修饰变量一般与static进行联合使用
final修饰的类不能被继承
final修饰的方法可以被继承,但是不能被重写(覆写)
-java中的继承到底继承了什么?
哪些东西能被继承,哪些东西不能被继承?
- 普通的成员变量,和成员方法 可以被继承
- 常量(final修饰的)可以被继承
- static修饰的成员可以被继承
- final修饰的方法可以被继承,但是不能被重写
- 构造方法不能被继承
- private修饰的成员可以被继承,只是
不可见(访问权限不够)
4.多态
通用编程
如果赋值给父类的引用,则只能调用父类中公共的方法和属性 如果赋值给本类的引用,不仅可以调用父类公共的成员,还调用本类自己特有的成员
多态的目的:就是当一个类去调用方法时,我想根据传入不同的参数,去执行他们各自的行动。
父类的引用指向子类对象(简化代码)
弊端:如果子类有自己特有的方法,那么多态则无法调用
Pet pet = new Dog(); (向上转型) //Pet是父类,把父类赋值给子类
Pet pet = new Pig();
Pet pet = new Cat();
向下转型:
//写一个方法,根据传入的对象去调用子类特有的方法。但是返回值还必须是父类
public Pet search(Pet pet){
if(pet instanceof Dog){
//向下转型
Dog dog = (Dog) pet;
dog.Playdish();
return dog;
}else{
Peguin peguin=(Peguin) pet;
peguin.swmming();
return peguin;
}
}
package day01.duotai;
public class Test{
public static void main(String[] args){
//父类的引用指向了子类
Pet pet = new Peguin();
//调用父类中有的方法(子类重写的方法)
pet.toHospital();
//现在想用多态的形式,去调用子类特有的方法,调用不了,怎么办?
//向下转型出现了
Pet pet2 = new Dog();
Master master = new Master();
master.seeHeath(pet2);
}
}
解决方案:就是帮助我们使用多态的方式去调用子类中特有的方法。
多态的转换
package com.uplooking.demo05;
public class Main {
public static void main(String[] args) {
Person t1 = new Teacher();//多态
t1.name = "大头";
Person s1 = new Student();//创建子类对象
s1.name = "小明";
Teacher tt = (Teacher) t1;//把父类引用赋值给子类引用 OK的
Student ss = (Student) t1;//t1本质上是Teacher的对象,所以在这会出现类型转换异常ClassCastException
t1.say();
tt.say();
ss.say();
}
}
5.方法的重载(overload)与重写(覆写)(override)
-方法的重载
在同一个类中,两个方法名称相同,定义不同的两个方法之间的关系就是重载关系.
构造方法也可以重载。
-方法的重写
6.静态代码块
-静态代码快是类加载的时候jvm帮我们调用的;
除了静态代码快,还有一个是普通代码快
,普通代码块也是类加载时执行,但是在静态代码快之后执行
package com.uplooking.demo01;
public class Person {
//普通代码块
{
System.out.println("普通代码快");
}
//构造方法
Person() {
System.out.println("无参数的构造方法");
}
//静态代码快
static {
System.out.println("静态代码快..");
}
}
执行顺序 静态代码快>普通代码块>构造方法
我们前面学习过,普通方法的定义:
返回值类型 方法名称(参数列表){
方法体
}
抽象方法
的定义为:
abstract 返回值类型 方法名称(参数列表);
抽象方法使用abstract
关键字修饰
抽象方法没有方法体
含有抽象方法的类,必须定义为抽象类
含有抽象方法的类称为抽象类
//抽象类
public abstract class Phone {
//抽象类中虽然可以没有抽象方法,但是一般我们都会至少有一个抽象方法,因为如果一个抽象方法都没有,那么这个抽象类就没有任何意义,还不如定义一个普通类
}
抽象类和抽象方法的总结
模板
,我们的子类去做具体的实现-接口是什么?
接口其实就是比抽象类更加抽象的类
-接口的定义
package com.uplooking.demo03;
//接口的定义
public interface Phone {
public abstract void playCs();
//接口中的方法可以不加public abstract,系统会自动添加
void playCf();
}
接口中的方法可以不加abstract
关键字,系统会默认添加
接口中的方法也可以不加修饰符(接口只能使用public来修饰),默认不加会使用public
来进行修饰
一般都会省略public abstract
接口中的方法都是公共的抽象方法
接口中不能有变量,可以有常量,一般省略public static final
//接口的定义
public interface Phone {
//接口中的常量 可以省略 public static final
//public static final String NAME = "超级手机";
String NAME = "超级手机";//等价上面的写法
void playCs();
//接口中的方法可以不加public abstract,系统会自动添加
void playCf();
}
-接口的实现
/**
* 实现接口的类必须实现其全部的方法(抽象方法)
*/
public class HuaWei implements Phone {
@Override
public void playCs() {
}
@Override
public void playCf() {
}
}
-接口之间可以继承吗?
可以
package com.uplooking.demo04;
public interface Game extends Game0 {
void gaming();
}
-java中多继承与多实现
在java中不支持多继承,但是支持多实现
13.1 什么是内部类?
内部类就是在类里面定义的类
13.2 普通内部类的定义
13.3 普通内部类对象的创建
内部类对象依赖于外部类对象,所以创建内部类对象,首先得创建外部类的对象,再使用外部类的对象创建内部类的对象.
Person.Student s1 = new Person.new Student();
package com.uplooking.demo06;
public class Person {
private String name;//成员变量
public void setName(String name) {
this.name = name;
}
//成员方法
public void say() {
System.out.println("my names is " + this.name);
}
//普通的内部类
public class Student {
void study() {
//Person.this指的是当前内部类对象依赖的外部类对象
System.out.println(Person.this.name);
// System.out.println(name);
}
}
}
普通内部类访问外部类成员:
外部类名.this.外部类私有成员
**静态内部类:**就是使用static
关键字修饰的内部类
静态内部类访问成员是通过外部类的类名来访问的。
匿名内部类: 定义方法中的,没有名字的类
package com.uplooking.demo08;
public class Main {
public static void main(String[] args) {
Phone p30 = new Phone();
p30.name = "华为p30";
p30.playGame(new IGame() {
@Override
public void gaming() {
System.out.println("四键玩游戏");
}
});
p30.playGame(new IGame() {
@Override
public void gaming() {
System.out.println("六键玩游戏");
}
});
p30.playGame(new IGame() {
@Override
public void gaming() {
System.out.println("八键玩游戏");
}
});
p30.playGame(new IGame() {
@Override
public void gaming() {
System.out.println("十键玩游戏");
}
});
}
}
总结: 匿名内部类是用来 实例化
抽象类和接口;
思想: 前辈的思想
设计模式: 就是前辈给我们总结的优秀的思想
设计模式与编程语言没有任何关系
比较著名的设计模式有23种(单例,构造,工厂,代理…)
16.1 单例设计模式
需求: 创建一个类,这个类的对象全局只有一个?
想法:
①让外部不能直接
new
对象(自己写一个无参数的构造方法,并且把这个构造方法私有化) ②类的里面对外部提供一个创建对象的方法,创建对象的方法里面就可进行对象的创建(但是如果每次都在方法中直接new,还是创建了好多的对象)
③我们就可以在方法中做判断,看这个对象时候被创建过,如果被创建过,则直接返回这个已经被创建的对象,如果没有被创建过,则创建一个新对象返回;
代码实现:
package com.uplooking.demo09;
import com.uplooking.demo06.Person;
public class Phone {
String name;
private static Phone phone;
//1.构造方法私有化
private Phone() {
}
//2.对外提供一个共有的创建对象的方法
public static Phone getInstance() {
if (phone == null) {
phone = new Phone();
}
return phone;
}
}
package com.uplooking.demo09;
public class Main {
public static void main(String[] args) {
Phone p1 = Phone.getInstance();
Phone p2 = Phone.getInstance();
Phone p3 = Phone.getInstance();
Phone p4 = Phone.getInstance();
System.out.println(p1);
System.out.println(p2);
System.out.println(p3);
System.out.println(p4);
}
}
com.uplooking.demo09.Phone@4554617c
com.uplooking.demo09.Phone@4554617c
com.uplooking.demo09.Phone@4554617c
com.uplooking.demo09.Phone@4554617c
单例模式的实现:
static
的本类对象,作为成员变量static
的方法,返回对象,方法中进行对象非空的判断16.2 单例设计模式的实现方式
懒汉模式
package com.uplooking.demo09;
public class Phone {
String name;
private static Phone phone;
//1.构造方法私有化
private Phone() {
}
//2.对外提供一个共有的创建对象的方法
public static Phone getInstance() {
if (phone == null) {
phone = new Phone();
}
return phone;
}
}
饿汉模式
package com.uplooking.demo09;
public class Phone {
String name;
private static Phone phone = new Phone();
//1.构造方法私有化
private Phone() {
}
//2.对外提供一个共有的创建对象的方法
public static Phone getInstance() {
return phone;
}
}