抽象和接口
1.代码块
1.1 什么是代码块
1.可以看成是一块代码,一般都是有 { };括起来
2.看到{} 应该想到作用域问题;
3.也就是代码的访问范围:
4.比如:这个j在if { }结构外面是无法访问的
class Test {
public static void main(String[] args) {
int i = 10;
if(i>=100){
int j = 100;
}
System.out.println(j);
}
}
1.2 分类-局部代码块[普通代码块]
1.概念:一般由大括号 { } 括起来,写在方法体中的,代码块就是局部代码块
//测试类
class Test {
public static void main(String[] args) {
System.out.println(123456);
{
System.out.println(654321);
}
System.out.println(666666);
}
}
---------- Java ----------
123456
654321
666666
输出完成 (耗时 0 秒) - 正常终止
2.如上代码都是按照顺序在执行
3.一般的在方法里面直接写{} 没有多大实际意义,结合 if for来写才有意义
1.3 分类-构造代码块
1.构造代码块:写在类结构体中的代码块,没有static修饰;
2.编译完毕之后会在每一个构造方法里面复制一份;
3.创建一个对象时[调用一次构造方法]就会执行一次构造代码块里面的代码
4.可以给对象的实例字段初始化值[其实用得非常的少]
5.//测试类源文件
class Test {
final int i;
public static void main(String[] args) {
}
{
i = 10;
System.out.println(10);
}
Test(){
}
Test(int i){
}
1
2
3
4
5
6
7
8
9
}
6.编译之后的文件
7.测试
public static void main(String[] args) {
new Test();
new Test(1);
}
---------- Java ----------
10
10
输出完成 (耗时 0 秒) - 正常终止
1.4 分类-静态代码块
1.直接写在类的结构体中,有static修饰的代码块;
2.在类加载的时候执行和创建对象没有关系;
3.优先于主方法执行
4.作用:可以在类加载的时候做已写初始化的操纵
//测试类
class Test {
public static void main(String[] args) {
System.out.println(“主方法”);
}
static {
System.out.println(“静态代码块”);
}
}
---------- Java ----------
静态代码块
主方法
输出完成 (耗时 0 秒) - 正常终止
2.继承与组合关系
2.1什么是组合
1.当设计一个Student类,用其他类型作为Student类的字段,来描述Student类的静态属性,此时就是组合关系
2.class Student{//描述学生这一类的事物
String name;//用了另外一个类,描述学生的静态属性
}
3.String :描述了字符串的这一类事务
2.2 组合关系设计示例
1.示意图:需求:设计一个手机类,存在手机卡:手机类可以查询手机号码
2.Card类表示手机卡:Card是一种数据类型
class Card{
String phoneNum;
Card(String phoneNum){
this.PhoneNum = PhoneNum;
}
public String getPhoneNum(){
return phoneNum;
}
}
3.手机CellPhone:Card类型作为CellPhone的一个字段:描述CellPhone的静态属性手机卡
class CellPhone{
Card card;
CellPhone(Card card){
this.card = card;
}
public void showPhoneNum(){
String num = this.card.getPhoneNum();
System.out.println(“您的靓号是:”+num);
}
}
4.测试组合关系的使用:
//测试类
class Test {
public static void main(String[] args) {
Card card = new Card(“15982889885”);
CellPhone cphone = new CellPhone(card);
cphone.showPhoneNum();
}
5.JMV堆栈内存图示意分析:
- 枚举
3.1 什么是枚举
1.枚举看成是 一个和 类 非常类似的新结构;
2.枚举的出现解决了问题: 很轻松设计一种类型,让它的值只有固定个数,用于像性别这样的数据
3.2枚举的基本语法
1.声明语法:
enum 枚举类名字{
字段
方法
构造方法 - 枚举中的构造方法默认都是private修饰,不能够是public
}
2.一般枚举类型也是写在一个Java文件中,编译完毕也会生成字节码文件
3.每一个自定义的枚举类型都(隐式的)拓展至 Enum 类,因此我们的枚举对象可以调用到Enum中的方法的(看API )
4.自己百度测试switch使用枚举 以及回顾switch相关的语法
3.3枚举示例代码及拓展
1.示例代码: 设计一个性别的枚举类型
enum Sex{
男,女
}
2.上面代码中 男 女 就是Sex类型的两个对象
//测试类
class Test {
public static void main(String[] args) {
System.out.println(Sex.男);
System.out.println(Sex.女汉子);
}
}
---------- Java ----------
男 为什么输出的是男 女汉子,枚举拓展在说明
女汉子
输出完成 (耗时 0 秒) - 正常终止
3.分析: 其实上面的写法是不推荐的(其中的对象字段不应该使用中文),应该这样写:【常见的写法】
enum Sex{
MAN,WOMAN
}
4.拓展: (希望打印上面的对象的时候打印出来是中文)
1)在每一个枚举对象中内置一个String类型的字段保存中文描述;
2)在创建每一个枚举对象的时候给中文描述字段赋值
3)覆写toString,返回当前枚举对象的中文描述
enum Sex{
MAN(“男”),WOMAN(“纯爷们”);
String name;//为了跟枚举常量添加中文描述
Sex(String name){//声明构造方法初始化枚举常量的值
this.name = name;
}
@Override
public String toString(){
return this.name;
}
}
3.4 枚举拓展自Object
1.枚举拓展至Enum类,但是继承关系不能显示的写出来
2.枚举里面toString方法 从哪里来?从Object类来
3.Enum类是Object的子类
java.lang.Object
java.lang.Enum
这是所有 Java 语言枚举类型的公共基本类。
4.抽象
1.抽象类是一个跟类一样的结构,抽象类本质也是一个类
2.类中有的成员,抽象类都可以有(字段 方法 构造方法),此外抽象类中还可以有抽象方法
abstract class Graph{
int i = 10;//抽象类中定义字段
public void add(){//抽象类中定义普通方法
}
Graph(){//抽象类中定义构造方法
}
}
3.抽象类不能够实例化
//测试类
class Test {
public static void main(String[] args) {
new Graph();
}
}
Test.java:4: 错误: Graph是抽象的; 无法实例化
new Griph();
^
1 个错误
输出完成 (耗时 0 秒) - 正常终止
4.抽象类的使用场景: 一般作为父类(基类,模板类),模板方法模式
5.支持多多态写法
4.3抽象方法
1.使用abstract 修饰的方法就是抽象方法没有方法主体;
2.抽象方法必须存于抽象类中[接口也可以],不能够放在普通类中
3.抽象类的子类
a)非抽象类必须覆写父类中的所有的抽象方法,
b)抽象类不用覆写父类中的抽象方法
4.4 抽象应用示例[会写]
class Test{
public static void main(String[] args) {
Graph g1 = new Circle();
}
Graph getP(){
return new Circle();//多态返回值形式,方法返回的是抽象类类型:所以方法内部,必然返回的是抽象类的子类对象
}
}
abstract class Graph{
abstract int getLength();//
}
class Circle extends Graph{
double r;//半径
int getLength(){
return 0;
}
}
4.5小结
1.为什么需要抽象:因为提取的公共的模板方法,根本没必要做任何实现,并且应该提示继承的类必须覆写
2.什么是抽象:
(1)abstract 修饰的类及方法 : 不创建对象
3.抽象类:abstract 修饰的一个类就是抽象类,字段普通方法,构造方法,都可以有,但是可以有抽象方法
4.抽象方法:abstract
(1)修饰的一个方法就是抽象方法,只能存在于抽象类及接口中 没有方法体,
(2)子类非抽象类,必须覆写抽象方法
5.抽象的作用: 模板类,基类,根类:主要作为公共的模板,提取公共的属性放到里面,让其他的子类继承,自己不能创建对象
5.接口
5.1 接口的引入
1.同学们有没有听说过接口
接口以前已经提到过,比如 引用类型 包括 类 接口 数组 枚举,或者抽象方法可以存在抽象类或者接口里面;
提到接口 ,会想到啥?
2.现实生活中 USB接口
a)插入充电宝:在充电宝端实现了充电功能
b)插入手机:在手机端实现了数据传入,及充电功能
c)插入键盘:在键盘端实现了键盘输入
d)插入鼠标:在鼠标端实现了鼠标功能
3.USB接口的体会:插入不同的设备实现不同的功能
5.2程序(软件开发)中的接口
1.对于接口有两种理解
1)软件与软件之间数据交互的接口【面试一般问的这个接口】
2)java中的接口
2.Java中的接口:是一个跟类很相似的结构
3.接口的语法:
interface 接口名{
}
4.接口一般写在一个独立的Java文件中,编译完毕之后也会生成独立的字节码文件
5.接口内部成员参考类
a)可以有字段:默认public static final 修饰的全局常量
b)方法全部都是抽象方法【没有 static final修饰 因为修饰的不能覆写,抽象方法需要覆写才有意义 】
c)构造方法没有
interface USB{
int i = 10;//默认public static final 修饰
void add();//默认public abstract 修饰
}
5.3接口如何使用
1.从结构上来看,接口中有全局常量和抽象方法
a)全局常量 : 接口名.常量名 直接调用
b)抽象方法 : 类实现接口,覆写接口中的抽象方法
c)子接口继承父接口,拓展接口
d)接口也是支持多态的写法的
5.4类实现接口
1.定义一个类来实现(implements)接口语法
interface A{}
class B implements A{
B非抽象类,必须全部覆写接口中的抽象方法
}
2.A接口类型相当于是B类型的父类:支持多态写法
A a1 = new B(); // 多态的写法
a1.eat(); // 多态方法调用
3.一个类其实可以实现多个接口,需要覆写所有接口中的抽象方法
4.一个类可以在继承一个类的同时实现多个接口,但是继承的代码必须写实现前面
5.5接口-接口 拓展(extends 继承)
1.接口与接口之间支持允许继承
2.一个接口可以继承多个接口
*6. 内部类
6.1什么是内部类
1.内部类:把一个类定义在另外一个类的内部,嵌套类,宿主类。[外部类的一个成员]
2.内部类编译完毕也会生成独立的字节码文件: 外部类名内部类名.class3.本质也是一个类!6.2真实的使用场景1.一般来说,类都应该是独立的写在一个自己的Java文件中;2.本质效果相当于是一种封装;3.示例:例如手机类,手机卡类存在于同一个项目中,如果说手机卡类的存在仅仅在手机类中有意义(只有手机类的内部会用到手机卡),为了更好的封装,把手机卡类整体移动到手机类中去,其它所有代码都不变。6.3语法层面验证(实用性不大)1.内部类编译完毕也会生成独立的字节码文件,外部类名 内部类名.class3.本质也是一个类!6.2真实的使用场景1.一般来说,类都应该是独立的写在一个自己的Java文件中;2.本质效果相当于是一种封装;3.示例: 例如手机类,手机卡类存在于同一个项目中,如果说手机卡类的存在仅仅在手机类中有意义(只有手机类的内部会用到手机卡),为了更好的封装,把手机卡类整体移动到手机类中去,其它所有代码都不变。6.3语法层面验证(实用性不大)1.内部类编译完毕也会生成独立的字节码文件,外部类名内部类名.class3.本质也是一个类!6.2真实的使用场景1.一般来说,类都应该是独立的写在一个自己的Java文件中;2.本质效果相当于是一种封装;3.示例:例如手机类,手机卡类存在于同一个项目中,如果说手机卡类的存在仅仅在手机类中有意义(只有手机类的内部会用到手机卡),为了更好的封装,把手机卡类整体移动到手机类中去,其它所有代码都不变。6.3语法层面验证(实用性不大)1.内部类编译完毕也会生成独立的字节码文件,外部类名内部类名.class;
2.语法上面再外部类的外部来尝试访问内部类以及内部类中的成员如下的效果,但实际开发中一般不这样写
class TestInnerClass {
/
内部类:类中的一个类叫做内部类!本质还是一个类而已
没啥可学的!本质已经学完类的语法了,所以内部类的语法基本类似,当做一个类来就行了
内部类有啥用:
在适当的时候,可以有更好的封装:例如手机卡:
*/
public static void main(String[] args) {
//Inner in = new Inner();//内部类,如此使用创建对象不行
//①非静态内部类创建对象,本质是类中的成员,想要类中成员来创建对象:[得通过外部类的对象访问]
Outer.Inner inner = new Outer().new Inner();
System.out.println(inner);
//②静态内部类创建对象,本质是类中的成员,想要类中成员来创建对象:[得通过外部类访问]
Outer.Inner1 inner1 = new Outer.Inner1();
System.out.println(inner1);
/*
③非静态内部类中的方法的方法
1.静态的方法:不能声明静态方法
2.非静态的方法:通过内部类的对象访问
/
inner.run();
/
④静态内部类中的方法的方法
1.静态的方法:
2.非静态的方法
*/
Outer.Inner1.eat();
inner1.run();
class Outer{
class Inner{//非静态的内部类
//static void eat(){//不能声明静态方法
// System.out.println(“非静态的内部类的静态方法”);
//}
void run(){//不能声明静态方法
System.out.println(“非静态的内部类的非静态方法”);
}
static class Inner1{//静态的内部类
static void eat(){//不能声明静态方法
System.out.println(“静态的内部类的静态方法”);
}
void run(){//不能声明静态方法
System.out.println(“静态的内部类的非静态方法”);
}
6.4 匿名内部类(匿名内部类对象的创建)
有对象了,就该有类,但是看不到名字,就是匿名内部类