【原】Java学习笔记018 - 面向对象
package cn.temptation; public class Sample01 {
public static void main(String[] args) {
// 继承关系的子类可以重写父类给它的成员方法
// 有时,父类不希望它的成员方法被子类重写(覆盖),对于这种要求,如何处理?
// 答:首先会想到把public 改为 private,但是这样会导致外部无法调用该方法。所以,Java提供了 final 关键字 // final 使用格式:
// 修饰符 final 成员方法(...) { ... } }
} //class Father {
//// public void show() {
//// System.out.println("这是父类的show方法");
//// }
//
// public final void show() {
// System.out.println("这是父类的show方法");
// }
//}
//
//class Baby extends Father {
// // 父类的show方法使用final修饰后,子类中就无法再重写show方法了
// // 语法错误:Cannot override the final method from Father
//// public void show() {
//// System.out.println("这是子类的show方法");
//// }
//}
package cn.temptation; public class Sample02 {
public static void main(String[] args) {
// final关键字可以用来修饰 成员变量、成员方法 和 类 // final修饰类,该类不能被继承 // final修饰类的理解:断子绝孙
}
} final class Test { } // Test类使用final修饰后,不能被继承
// 语法错误:The type TestEx cannot subclass the final class Test
//class TestEx extends Test {
//
//}
package cn.temptation; public class Sample03 {
public static void main(String[] args) {
// final修饰成员变量:赋值一次后不能再进行赋值
// Child child = new Child();
// child.show(); // 常量:
// 1、字面量常量:true、false、123、'a'、"China"
// 2、自定义常量:使用final修饰符修饰的成员变量 final int i = 2; // 所以,自定义常量一般也使用常量的编码规范:即全部字母均大写,如果是多个单词组成,使用下划线_连接
}
} //class Parent {
// public int i = 2;
// public final int j = 4;
//
// // 对于非final修饰的成员变量,不进行初始化赋值,是可以使用其默认值
// public int x;
// // 对于final修饰的成员变量,必须进行初始化赋值
// // 语法错误:The blank final field y may not have been initialized
//// public final int y;
// // 先定义成员变量y,接着进行赋值也是有语法错误
//// y = 123;
//
// // 自定义常量一般也使用常量的编码规范:即全部字母均大写,如果是多个单词组成,使用下划线_连接
// public final int K = 100;
// public final boolean CHECK_FLAG = true;
//}
//
//class Child extends Parent {
// public void show() {
// // 下面两组代码效果相同
//// this.i = 3;
//// System.out.println(this.i);
//
// super.i = 3;
// System.out.println(super.i);
//
// // final修饰的成员变量不能被改变
// // 语法错误:The final field Parent.j cannot be assigned
//// this.j = 5;
//// System.out.println(this.j);
// // 语法错误:The final field Parent.j cannot be assigned
//// super.j = 5;
//// System.out.println(super.j);
// }
//}
package cn.temptation; public class Sample04 {
public static void main(String[] args) {
// final修饰局部变量
// 1、final修饰值类型的局部变量,赋值一次后不能再赋值
// 2、final修饰引用数据类型的局部变量,new过一次后不能再new了,创建过一次引用数据类型对象后就不能再创建了
// 也就是说该局部变量在堆中有一个内存空间后就不能再创建新的内存空间了 int i = 2;
System.out.println(i);
i = 3;
System.out.println(i); final int j = 4;
System.out.println(j);
// The final local variable j cannot be assigned. It must be blank and not using a compound assignment
// j = 5;
// System.out.println(j); System.out.println("--------------------------------------"); // Demo demo = new Demo();
// System.out.println(demo);
// System.out.println(demo.k);
// demo = new Demo();
// demo.k = 88;
// System.out.println(demo);
// System.out.println(demo.k); final Demo demoEx = new Demo();
System.out.println(demoEx);
System.out.println(demoEx.k);
// The final local variable demoEx cannot be assigned. It must be blank and not using a compound assignment
// demoEx = new Demo();
demoEx.k = 77;
System.out.println(demoEx);
System.out.println(demoEx.k); // 注意:
// 使用final修饰的引用数据类型的局部变量虽然不能更改其在堆内存中创建的空间地址,但是其在堆内存中的成员变量的值还是可以修改的
}
} class Demo {
int k = 99;
}
package cn.temptation; public class Sample05 {
public static void main(String[] args) {
// 使用final、final static修饰的成员变量 与 构造代码块内外 赋值的问题 TestEx testEx = new TestEx();
}
} class TestEx {
// 成员变量
int i = 2; // 语法错误:The blank final field j may not have been initialized
final int j; final int k = 3; final static int m = 4; // 语法错误:The blank final field n may not have been initialized
// final static int n; final int x = 123; final static int y = 987; // 构造代码块
{
System.out.println(i);
i = 3;
System.out.println(i); System.out.println(k); // 语法错误:The blank final field j may not have been initialized
// System.out.println(j);
// 在构造代码块之前使用final修饰成员变量并不赋值,在构造代码块中进行赋值,语法OK
j = 5;
System.out.println(j); // 在构造代码块之前使用final static修饰成员变量并不赋值,在构造代码块中进行赋值,语法也出错
// 语法错误:The final field TestEx.n cannot be assigned
// n = 6;
// System.out.println(n); System.out.println(x);
// 对于构造代码块之前已经赋值的final修饰的成员变量,在构造代码块中进行赋值,语法也出错
// 语法出错:The final field TestEx.x cannot be assigned
// x = 456;
// System.out.println(x); System.out.println(y);
// 对于构造代码块之前已经赋值的final static修饰的成员变量,在构造代码块中进行赋值,语法也出错
// 语法出错:The final field TestEx.y cannot be assigned
// y = 654;
// System.out.println(y);
}
}
package cn.temptation; public class Sample06 {
public static void main(String[] args) {
// 多态的引入:
// 变形金刚:变化为不同的形态:一会儿是机器人,一会儿变成汽车
// 水:三种不同的形态:气态、液态、固态 // 多态:同一个对象,在不同的时间、场合表现出不同的形态或状态 // 比如:狗这个动物就是可爱啊!
// 这句话其实有几层意思:
// 1、狗是一种动物,也就是说狗从动物继承而来的,dog is an animal
// 2、描述的重点在动物上,这个动物在我们描述的时候以狗这种形态出现的
// 类似:猫这个动物就是要人哄啊! // 多态的前提:
// 1、继承是多态的基础,必须有继承的关系,才可以探讨多态
// 2、要有override重写
// 3、要有父类的引用(声明)指向子类的对象:父类 对象名 = new 子类(); 父类在前,子类在后
// 对比:之前写法 子类 对象名 = new 子类(); // 理解:
// 狗 对象名 = new 狗(); 狗 是 狗 √
// 动物 对象名 = new 狗(); 狗 是 动物 √
// 狗 对象名 = new 动物(); 动物 是 狗 × // Son son = new Son();
// System.out.println(son); // Father obj = new Son();
// System.out.println(obj); // 语法错误:Type mismatch: cannot convert from Father to Son
// Son obj = new Father();
// System.out.println(obj); // 多态中成员的关系:
// 1、成员变量
// 编译时去赋值号左侧的类型里找,执行时去赋值号左侧的类型里找
// 2、构造函数
// 是否是多态的写法不影响,都是通过继承关系先找到父类的构造函数,执行后再走入子类的构造函数
// 3、成员方法
// 编译时去赋值号左侧的类型里找,执行时去赋值号右侧的类型里找
// 4、静态成员变量
// 编译时去赋值号左侧的类型里找,执行时去赋值号左侧的类型里找
// 5、静态成员方法
// 编译时去赋值号左侧的类型里找,执行时去赋值号左侧的类型里找 // 非多态写法
// Son son = new Son();
// System.out.println(son); // cn.temptation.Son@15db9742
// System.out.println(son.i); // 3
// son.show(); // 子类的show方法
// System.out.println(son.m); // 5
// System.out.println(Son.m); // 5
// son.use(); // 子类的静态use方法
// Son.use(); // 子类的静态use方法 // 多态写法
Father obj = new Son();
System.out.println(obj); // cn.temptation.Son@15db9742
System.out.println(obj.i); //
obj.show(); // 子类的show方法
System.out.println(obj.m); //
System.out.println(Father.m); //
System.out.println(Son.m); //
obj.use(); // 父类的静态use方法
Father.use(); // 父类的静态use方法
Son.use(); // 子类的静态use方法 // 注意:
// 多态时,需要从 编译时 和 执行时 两个方面去观察
// 多态中,非静态的成员方法在执行时去赋值号右侧的类型中找相应的方法进行调用,这种调用也称为 后期调用
}
} // 父类
class Father {
// 成员变量
public int i = 2;
public static int m = 4; // 构造函数
public Father() {
System.out.println("父类的构造函数");
} // 成员方法
public void show() {
System.out.println("父类的show方法");
} public static void use() {
System.out.println("父类的静态use方法");
}
} // 子类
class Son extends Father {
// 成员变量
public int i = 3;
public static int m = 5; // 构造函数
public Son() {
System.out.println("子类的构造函数");
} // 成员方法
public void show() {
System.out.println("子类的show方法");
} public static void use() {
System.out.println("子类的静态use方法");
}
}
package cn.temptation; public class Sample07 {
public static void main(String[] args) {
// 不用装刘备的时候,可以做自己,就可以用自己特有的play方法
// LiuShan personEx = new LiuShan();
// personEx.work();
// personEx.play(); // 让刘禅接替刘备的位置(多态的使用)
LiuBei person = new LiuShan();
System.out.println(person); // cn.temptation.LiuShan@15db9742
person.work();
// 让刘禅装刘备时,不能做自己,不能使用自己特有的play方法
// 语法错误:The method play() is undefined for the type LiuBei
// person.play();
// 问:非要使用子类中特有的成员方法,怎么办? 答:因为我们知道其对象其实是子类类型的对象,所以可以考虑使用一下强制类型装换
((LiuShan)person).play();
}
} // 父类:刘备
class LiuBei {
public void work() {
System.out.println("千辛万苦打江山!");
}
} // 子类:刘禅
class LiuShan extends LiuBei {
// 成员方法
// 重写父类的成员方法work
public void work() {
System.out.println("被逼着做主公,也不知道有多难受!");
} // 子类特有的成员方法play
public void play() {
System.out.println("玩的都乐不思蜀了!");
}
}
package cn.temptation; public class Sample08 {
public static void main(String[] args) {
// 多态的优点:
// 1、使用多态,让程序有较好的扩展性
// 2、使用多态,让程序由较好的健壮性(没有继承关系的两个类不能玩多态) // 不使用多态的写法
// BasketBall basketBall = new BasketBall();
// basketBall.play();
//
// FootBall footBall = new FootBall();
// footBall.play();
//
// VolleyBall volleyBall = new VolleyBall();
// volleyBall.play(); // 使用多态的写法
// 写法1
// Sport basketBall = new BasketBall();
// basketBall.play();
//
// Sport footBall = new FootBall();
// footBall.play();
//
// Sport volleyBall = new VolleyBall();
// volleyBall.play(); // 写法2
// Sport sport1 = new BasketBall();
// sport1.play();
//
// Sport sport2 = new FootBall();
// sport2.play();
//
// Sport sport3 = new VolleyBall();
// sport3.play(); // 写法3(数组的动态初始化)
// 因为上面三个变量的类型都是一致的,所以考虑使用数组来存放一下,声明一个Sport类型的数组
// Sport[] sports = new Sport[3];
// sports[0] = new BasketBall();
// sports[1] = new FootBall();
// sports[2] = new VolleyBall(); // 写法4(数组的静态初始化)
Sport[] sports = {
new BasketBall(), // 匿名对象
new FootBall(),
new VolleyBall(),
new Swim()
}; for (Sport item : sports) {
item.play();
}
}
} // 父类:运动类
class Sport {
public void play() {
System.out.println("做运动");
}
} // 子类:篮球类
class BasketBall extends Sport {
@Override
public void play() {
System.out.println("篮球的玩法");
}
} class FootBall extends Sport {
@Override
public void play() {
System.out.println("足球的玩法");
}
} class VolleyBall extends Sport {
public void play() {
System.out.println("排球的玩法");
}
} class Swim extends Sport {
@Override
public void play() {
System.out.println("游泳的玩法");
}
}
package cn.temptation; public class Sample09 {
public static void main(String[] args) {
// 多态的缺点:
// 使用多态,对于子类有但是父类没有的成员方法(子类特有的成员方法),无法使用
// Parent obj = new Child();
// obj.show(); // 语法错误:The method use() is undefined for the type Parent
// obj.use(); // 要想使用子类特有的成员方法,只有在明确其实该对象是子类类型的对象时,进行强制类型转换
// ((Child)obj).use();
}
} //class Parent {
// public void show() {
// System.out.println("父类的成员方法");
// }
//}
//
//class Child extends Parent {
// @Override
// public void show() {
// System.out.println("子类的成员方法");
// }
//
// public void use() {
// System.out.println("子类特有的成员方法");
// }
//}
package cn.temptation; public class Sample10 {
public static void main(String[] args) {
// 对于多态的缺点:使用多态,对于子类有但是父类没有的成员方法(子类特有的成员方法),无法使用,非要使用,怎么办?
// 方法1、在父类中加上子类特有的成员方法,语法OK,但是不能这样写,因为这样就违背了父类设计的初衷
// 方法2、因为子类实际在替代父类的事情,所以在编译阶段只能用父类中的成员方法,
// 如果明确实际使用的是子类对象,使用时让其改为子类的类型,就可以使用其自己的成员方法了
// 把父类类型的变量名(引用)强制类型转换为子类类型的引用,称为多态的向下转型 // Parent obj = new Child();
// obj.show();
// 语法错误:The method use() is undefined for the type Parent
// obj.use(); // Parent obj = new Child();
// // 写法1
//// ((Child)obj).show();
//// ((Child)obj).use();
// // 写法2
// Child child = (Child) obj;
// child.show();
// child.use();
//
// // 不转型
// Child childEx = new Child(); // 所谓的转型:就是拿着赋值号右边的类型 和 赋值号左边的类型进行比较
// 右边的类型是左边类型的下级(子),向上转型
// 右边的类型是左边类型的上级(父),向下转型
Parent obj = new Child(); // 向上转型
Child child = (Child)obj; // 向下转型 // 没有关系的两个类,是无法进行强制类型转换的
// 语法错误:Cannot cast from Parent to Other
// Other other = (Other)obj;
}
} class Parent {
public void show() {
System.out.println("父类的成员方法");
}
} class Child extends Parent {
@Override
public void show() {
System.out.println("子类的成员方法");
} public void use() {
System.out.println("子类特有的成员方法");
}
} class Other {
public void show() {
System.out.println("其他类的成员方法");
}
}
package cn.temptation; public class Sample11 {
public static void main(String[] args) {
// 多态的一些问题:
// 1、父类、子类都有的同名同参数列表成员方法,编译时找父类的成员方法,执行时找子类的成员方法
// 2、父类有、子类没有的成员方法,编译时找父类的成员方法,执行时找父类的成员方法(因为子类中没有重写该成员方法,所以使用父类中的成员方法)
ParentTest obj = new ChildTest();
obj.show();
}
} class ParentTest {
public void show() {
System.out.println("父类有、子类没写的成员方法");
}
} class ChildTest extends ParentTest { }
package cn.temptation; public class Sample12 {
public static void main(String[] args) {
Animal animal = new Dog();
animal.eat();
// animal.guard(); // 语法错误 Dog dog = (Dog) animal;
dog.guard(); // 执行出错,产生异常:java.lang.ClassCastException: cn.temptation.Dog cannot be cast to cn.temptation.Cat
// 原因:
// 第5行的animal变量是一个引用,animal变量的类型是Animal类类型,它指向堆内存中创建出的Dog类型的空间
// 下句的强制类型转换,是要把animal这个引用转换为Cat类型,如果正常的使用,那么这个cat变量的引用,应该指向堆内存中创建的Cat类型的空间
Cat cat = (Cat) animal; // 这句语法上没有错误,编译可以通过,是因为有继承关系的子类和父类可以进行向上转型 和 向下转型
cat.eat();
cat.bask();
// 本质上这样的写法就是"指鹿为马" // 平行的两个子类,是无法进行强制类型转换的
Dog dogEx = new Dog();
Cat catEx = new Cat();
// 语法错误:Cannot cast from Dog to Cat
// catEx = (Cat)dogEx;
}
} class Animal {
public void eat() {
System.out.println("动物都会吃");
}
} class Dog extends Animal {
@Override
public void eat() {
System.out.println("狗吃肉");
} public void guard() {
System.out.println("看门");
}
} class Cat extends Animal {
@Override
public void eat() {
System.out.println("猫吃鱼");
} public void bask() {
System.out.println("晒太阳");
}
}
【原】Java学习笔记018 - 面向对象的更多相关文章
- Java学习笔记之---面向对象
Java学习笔记之---面向对象 (一)封装 (1)封装的优点 良好的封装能够减少耦合. 类内部的结构可以自由修改. 可以对成员变量进行更精确的控制. 隐藏信息,实现细节. (2)实现封装的步骤 1. ...
- Java学习笔记之面向对象、static关键字
一周Java学习总结 今天就总结理清一下关于面向对象和面向过程的程序设计的一些不同特点,以及讲下static关键字. 面向对象 现在接触的Java是面向对象的,现在的程序开发几乎都是以面向对象为基础的 ...
- Java 学习笔记(4)——面向对象
现在一般的语言都支持面向对象,而java更是将其做到很过分的地步,java是强制使用面向对象的写法,简单的写一个Hello Word都必须使用面向对象,这也是当初我很反感它的一点,当然现在也是很不喜欢 ...
- 【原】Java学习笔记019 - 面向对象
package cn.temptation; public class Sample01 { public static void main(String[] args) { // 仔细想一想,Ani ...
- 【原】Java学习笔记016 - 面向对象
package cn.temptation; public class Sample01 { public static void main(String[] args) { // this 关键字 ...
- 【原】Java学习笔记014 - 面向对象
package cn.temptation; public class Sample01 { public static void main(String[] args) { // 面向对象思想 // ...
- 【原】Java学习笔记020 - 面向对象
package cn.temptation; public class Sample01 { public static void main(String[] args) { // 成员方法的参数列表 ...
- 【原】Java学习笔记017 - 面向对象
package cn.temptation; public class Sample01 { public static void main(String[] args) { // 继承关系中的pri ...
- 【原】Java学习笔记015 - 面向对象
package cn.temptation; public class Sample01 { public static void main(String[] args) { // 传递 值类型参数 ...
随机推荐
- 隔壁老主精讲web页面性能优化。
首先说一下为什么要进行web页面性能优化,在同样的网络环境下,两个同样能满足你的需求的网站,一个“Biu”的一下就加载出来了,一个卡--卡--卡--卡--卡--才出来,你会选择哪个?研究表明:用户最满 ...
- Linux 设置自启动服务
0 为停机,机器关闭.(千万不要把initdefault设置为0 ) 1 为单用户模式,就像Win9x下的安全模式类似. 2 为多用户模式,但是没有NFS支持. 3 为完整的多用户 ...
- 【Storm篇】--Storm 容错机制
一.前述 Storm容错机制相比其他的大数据组件做的非常不错. 二.具体原因 结合Storm集群架构图: 我们的程序提交流程如下: 其中各个组件的作用如下: Nimbus资源调度任务分配接收jar ...
- Python内置函数(25)——getattr
英文文档: getattr(object, name[, default]) Return the value of the named attribute of object. name must ...
- 如何在启用JWT Token授权的.NET Core WebApi项目中下载文件
背景 前几天,做项目的时候遇到一个文件下载的问题.当前系统是一个前后端分离的项目,前端是一个AngularJs项目, 后端是一个.NET Core WebApi项目.后端的Api项目使用了Jwt To ...
- gradle插件从3.2.0升级到3.2.1后报错Error: Cannot create directory 项目目录\thirdlib\build\intermediates\packaged_res\debug\drawable
报错信息如下: 解决方案: 删除thirdlib\build目录,然后重新编译. 但是紧接着又会报类似的错误,只不过build目录变成其他module的了. 所以,先clear build,然后再重 ...
- Android软键盘事件imeOptions响应
版权声明:本文为HaiyuKing原创文章,转载请注明出处! 前言 在android发开过程中,有时候需要对EditText的软键盘进行监听. 当点击软键盘回车位置按键的时候,需要实现 完成.前进.下 ...
- SpringBoot入门教程(十四)导出Excel
用JavaPOI导出Excel时,我们会考虑到Excel版本及数据量的问题.针对不同的Excel版本,要采用不同的工具类.HSSFWorkbook:是操作Excel2003以前(包括2003)的版本, ...
- 深入探究Lua的GC算法(上)-《Lua设计与实现》
对于内存的管理,是程序在应用的时候的必需知识点,<Lua设计与实现>中对Lua语言的GC原理做了一个详细的讲解,云风的blog也对其进行了详尽的讲解Lua GC 的源码剖析 系列 给出作者 ...
- Scrum到底是个神马玩意儿
从前有一种非常火爆的体育运动,对阵双方各派出11位猛男,在宽阔的草皮球场内争抢一颗可怜的小皮球.哪方能够通过团队协作拿到皮球,并且运送到对方场地的特定位置即得分. 没错,你没有走错片场,快到超级碗里来 ...