文档版本 | 开发工具 | 测试平台 | 工程名字 | 日期 | 作者 | 备注 |
---|---|---|---|---|---|---|
V1.0 | 2016.02.29 | lutianfei | none |
工具类中使用静态
帮助文档的制作
如何使用帮助文档
Math类学习
代码块
继承
继承概述
继承的好处
Java中继承的特点
Java中继承的注意事项
什么时候使用继承呢?
继承中成员变量的关系
super关键字
继承中构造方法的关系
继承中成员方法的关系
方法重写概述
方法重写的注意事项
练习题
工具类中使用静态
- 当报错无法从静态上下文中引用非静态 方法xxx:
- 表明在静态方法中引用了非静态方法
- 在工具类中当把构造方法私有后,外界就不能再创建对象了,此时将所有方法设为静态后。可以根据静态方法的特点:通过类名来调用。
- Eg:
/*
我想要对数组进行操作
在同一个文件夹下,类定义在两个文件中和定义在一个文件中其实一样的。
*/
class ArrayDemo {
public static void main(String[] args) {
//定义数组
int[] arr = {28,55,37,46,19};
//静态方法
//printArray(arr);
//非静态方法
//ArrayDemo ad = new ArrayDemo();
//ad.printArray(arr);
//测试类的作用:创建其他类的对象,调用其他类的功能。
//而我们现在的操作是跟数组相关的,所以,你应该把这些操作定义到数组操作类中
//定义一个数组的操作类
//有了数组操作类之后的调用
//ArrayTool at = new ArrayTool();
//at.printArray(arr);
//方法改进为静态后,就可以直接通过类名调用
ArrayTool.printArray(arr);
}
/*
public static void printArray(int[] arr) {
for(int x=0; x<arr.length; x++) {
if(x == arr.length-1) {
System.out.println(arr[x]);
}else {
System.out.print(arr[x]+", ");
}
}
}
*/
//假设该方法不是静态的
/*
public void printArray(int[] arr) {
for(int x=0; x<arr.length; x++) {
if(x == arr.length-1) {
System.out.println(arr[x]);
}else {
System.out.print(arr[x]+", ");
}
}
}
*/
}
class ArrayTool {
//把构造方法私有,外界就不能在创建对象了
private ArrayTool(){}
public static void printArray(int[] arr) {
for(int x=0; x<arr.length; x++) {
if(x == arr.length-1) {
System.out.println(arr[x]);
}else {
System.out.print(arr[x]+", ");
}
}
}
}
帮助文档的制作
- 制作工具类
- ArrayTools
- 制作帮助文档(API)
- javadoc -d 目录 -author -version ArrayTool.java
- 目录可以写一个文件的路径
- javadoc -d 目录 -author -version ArrayTool.java
- 制作帮助文档出错:
- 找不到可以文档化的公共或受保护的类:告诉我们类的权限不够。修改方法在类前面加
public
修饰。
如何使用帮助文档
- 点击
显示
,找到索引
,出现输入框
- 你应该知道你找谁?举例:Scanner
- 看这个类的结构(需不需要
导包
) 注:java.lang
包下的类不需要导入,其他的全部需要导入。- 成员变量 说明书中对照为
字段摘要
- 构造方法 说明书中对照为
构造方法摘要
- 有构造方法 : 创建对象
- 没有构造方法:成员可能都是静态的,通过类名调用。
- 成员方法
方法摘要
- 看左边
- 是否静态:如果静态,可以通过类名调用
- 返回值类型:定义返回的是说明,就用什么接收。
- 看右边
- 方法名,不要打错
- 参数列表:需要什么参数,就给什么,需要几个给几个
- 看左边
- 看版本说明
- 成员变量 说明书中对照为
- 看这个类的说明
- 看构造方法
- 看成员方法
Math类学习
/*
Math:类包含用于执行基本数学运算的方法
由于Math类在java.lang包下,所以不需要导包。
特点:
没有构造方法,因为它的成员全部是静态的。
掌握一个方法:
获取随机数
public static double random():返回带正号的 double 值,该值大于等于 0.0 且小于 1.0。
*/
class MathDemo {
public static void main(String[] args) {
//获取一个随机数
//double d = Math.random();
//System.out.println(d);
//需求:我要获取一个1-100之间的随机数,肿么办?
for(int x=0; x<100; x++) {
int number = (int)(Math.random()*100)+1;
System.out.println(number);
}
}
}
代码块
- 在Java中,使用{}括起来的代码被称为代码块,根据其位置和声明的不同,可以分为
局部代码块
,构造代码块
,静态代码块
,同步代码块
(多线程讲解)。 局部代码块
- 在方法中出现;限定变量生命周期,及早释放,提高内存利用率
构造代码块
- 在类中,方法外出现;
- 多个构造方法方法中相同的代码存放到一起,每次调用构造都执行,并且在
构造方法
前执行。- 作用:可以把多个构造方法中的共同代码放到一起。
静态代码块
- 在类中方法外出现,加了static修饰
- 在类中方法外出现,并加上static修饰;用于给类进行初始化,在加载的时候就执行,并且只执行一次。
- eg1 :
class Code {
static { //静态代码块
int a = 1000;
System.out.println(a);
}
//构造代码块
{
int x = 100;
System.out.println(x);
}
//构造方法
public Code(){
System.out.println("code");
}
//构造方法
public Code(int a){
System.out.println("code");
}
//构造代码块
{
int y = 200;
System.out.println(y);
}
//静态代码块
static {
int b = 2000;
System.out.println(b);
}
}
class CodeDemo {
public static void main(String[] args) {
//局部代码块
{
int x = 10;
System.out.println(x);
}
//找不到符号
//System.out.println(x);
{
int y = 20;
System.out.println(y);
}
System.out.println("---------------");
Code c = new Code();
System.out.println("---------------");
Code c2 = new Code();
System.out.println("---------------");
Code c3 = new Code(1);
}
}
/*
* 程序运行结果:
10
20
---------------
1000
2000
100
200
code
---------------
100
200
code
---------------
100
200
code
*/
- Eg2 :
class Student {
static {
System.out.println("Student 静态代码块");
}
{
System.out.println("Student 构造代码块");
}
public Student() {
System.out.println("Student 构造方法");
}
}
class StudentDemo {
static {
System.out.println("林青霞都60了,我很伤心");
}
public static void main(String[] args) {
System.out.println("我是main方法");
Student s1 = new Student();
Student s2 = new Student();
}
}
/*
写程序的执行结果。
林青霞都60了,我很伤心
我是main方法
Student 静态代码块
Student 构造代码块
Student 构造方法
Student 构造代码块
Student 构造方法
*/
继承
继承概述
- 多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中,那么多个类无需再定义这些属性和行为,只要继承那个类即可。
- 通过extends关键字可以实现类与类的继承
- **
class
子类名extends
父类名 {} **
- **
- 单独的这个类称为
父类
,基类
或者超类
;这多个类可以称为子类
或者派生类
。 - 有了继承以后,我们定义一个类的时候,可以在一个已经存在的类的基础上,还可以定义自己的新成员。
class Dad(){}
class Son extends Dad {}
继承的好处
- 提高了代码的复用性
- 多个类相同的成员可以放到同一个类中
- 提高了代码的维护性
- 如果功能的代码需要修改,修改一处即可
- 让类与类之间产生了关系,是多态的前提
- 其实这也是继承的一个弊端:类的耦合性很强
- 开发的原则:低耦合,高内聚
耦合
:类与类的关系。内聚
:就是自己完成某件事情的能力。
Java中继承的特点
- Java只支持单继承,不支持多继承。
- 一个类只能有一个父类,不可以有多个父类。
- class SubDemo extends Demo{} //ok
- class SubDemo extends Demo1,Demo2…//error
- 一个类只能有一个父类,不可以有多个父类。
- Java支持多层继承(继承体系)
- class A{}
- class B extends A{}
- class C extends B{}
Java中继承的注意事项
- 子类只能继承父类所有非私有的成员(成员方法和成员变量)
- 其实这也体现了继承的另一个弊端:打破了封装性
- 子类不能继承父类的构造方法,但是可以通过
super
关键字去访问父类构造方法。 - 不要为了部分功能而去继承
- Eg1:
class Father {
private int num = 10;
public int num2 = 20;
//私有方法,子类不能继承
private void method() {
System.out.println(num);
System.out.println(num2);
}
public void show() {
System.out.println(num);
System.out.println(num2);
}
}
class Son extends Father {
public void function() {
//num可以在Father中访问private
//System.out.println(num); //子类不能继承父类的私有成员变量
System.out.println(num2);
}
}
class ExtendsDemo3 {
public static void main(String[] args) {
// 创建对象
Son s = new Son();
//s.method(); //子类不能继承父类的私有成员方法
s.show();
s.function();
}
}
什么时候使用继承呢?
- 继承中类之间体现的是:”is a”的关系。
- 假设法:如果有两个类A,B。只有他们符合A是B的一种,或者B是A的一种,就可以考虑使用继承。
继承中成员变量的关系
- 案例演示
- 子父类中同名和不同名的成员变量
- 结论:
- 在子类方法中访问一个变量
- 首先在子类局部范围找
- 然后在子类成员范围找
- 最后在父类成员范围找(肯定不能访问到父类局部范围)
- 如果还是没有就报错。(不考虑父亲的父亲…)
super关键字
- super的用法和this很像
this
代表本类对应的引用。super
代表父类存储空间的标识(可以理解为父类引用)
- 用法(this和super均可如下使用)
- 访问
成员变量
- this.成员变量
- super.成员变量
- 访问
构造方法
(子父类的构造方法问题讲)- this(…) :调用本类的构造方法
- super(…):调用父类的构造方法
- 访问
成员方法
(子父类的成员方法问题讲)- this.成员方法()
- super.成员方法()
- 访问
继承中构造方法的关系
- 子类中所有的构造方法默认都会访问父类中空参数的构造方法
- 因为子类会继承父类中的数据,可能还会使用父类的数据。所以,子类初始化之前,一定要先完成父类数据的初始化。
- 每一个构造方法的第一条语句默认都是:super()
class Father {
int age;
public Father() {
System.out.println("Father的无参构造方法");
}
public Father(String name) {
System.out.println("Father的带参构造方法");
}
}
class Son extends Father {
public Son() {
//super();//默认都会有的
System.out.println("Son的无参构造方法");
}
public Son(String name) {
//super();//默认都会有的
System.out.println("Son的带参构造方法");
}
}
class ExtendsDemo6 {
public static void main(String[] args) {
//创建对象
Son s = new Son();
System.out.println("------------");
Son s2 = new Son("林青霞");
}
}
- 程序运行结果:
- 如果父类没有无参构造方法,那么子类的构造方法会出现什么现象呢,如何解决?
- 会报错
- 解决办法:
- A:在父类中加一个无参构造方法
- B:通过使用
super
关键字去显示的调用父类的带参构造方法
。
- 子类中一定要有一个访问了父类的构造方法,否则父类数据就没有办法初始化。
- 注:super(…)必须放在第一条语句上,否则就可能出现对父类的数据进行了多次初始化,所以必须放在第一条语句上面。
- 一个类的初始化过程
成员变量
进行初始化默认
初始化显示
初始化构造方法
初始化
- A:一个类的静态代码块,构造代码块,构造方法的执行流程
- 静态代码块 > 构造代码块 > 构造方法
- B:静态的内容是随着类的加载而加载
- 静态代码块的内容会优先执行
- C:子类初始化之前先会进行父类的初始化
- 练习1
/*
看程序写结果:
A:成员变量 就近原则
B:this和super的问题
this访问本类的成员
super访问父类的成员
C:子类构造方法执行前默认先执行父类的无参构造方法
D:一个类的初始化过程
成员变量进行初始化
默认初始化
显示初始化
构造方法初始化
结果:
fu
zi
30
20
10
*/
class Fu{
public int num = 10;
public Fu(){
System.out.println("fu");
}
}
class Zi extends Fu{
public int num = 20;
public Zi(){
System.out.println("zi");
}
public void show(){
int num = 30;
System.out.println(num); //30
System.out.println(this.num); //20
System.out.println(super.num); //10
}
}
class ExtendsTest {
public static void main(String[] args) {
Zi z = new Zi();
z.show();
}
}
- 练习2:
/*
看程序写结果:
A:一个类的静态代码块,构造代码块,构造方法的执行流程
静态代码块 > 构造代码块 > 构造方法
B:静态的内容是**随着类的加载而加载**
静态代码块的内容会优先执行
C:子类初始化之前先会进行父类的初始化
结果是:
静态代码块Fu
静态代码块Zi
构造代码块Fu
构造方法Fu
构造代码块Zi
构造方法Zi
*/
class Fu {
static {
System.out.println("静态代码块Fu");
}
{
System.out.println("构造代码块Fu");
}
public Fu() {
System.out.println("构造方法Fu");
}
}
class Zi extends Fu {
static {
System.out.println("静态代码块Zi");
}
{
System.out.println("构造代码块Zi");
}
public Zi() {
System.out.println("构造方法Zi");
}
}
class ExtendsTest2 {
public static void main(String[] args) {
Zi z = new Zi();
}
}
- 练习3(有难度理解不深刻)
/*
看程序写结果:
A:成员变量的问题
int x = 10; //成员变量是基本类型
Student s = new Student(); //成员变量是引用类型
B:一个类的初始化过程
成员变量的初始化
默认初始化
显示初始化
构造方法初始化
C:子父类的初始化(分层初始化)
先进行父类初始化,然后进行子类初始化。
结果:
YXYZ
问题:
虽然子类中构造方法默认有一个super()
初始化的时候,不是按照那个顺序进行的。
而是按照分层初始化进行的。
它仅仅表示要先初始化父类数据,再初始化子类数据。
*/
class X {
Y b = new Y();
X() {
System.out.print("X");
}
}
class Y {
Y() {
System.out.print("Y");
}
}
public class Z extends X {
Y y = new Y();
Z() {
//super
System.out.print("Z");
}
public static void main(String[] args) {
new Z();
}
}
继承中成员方法的关系
方法重写概述
- 子类中出现了和父类中一模一样的方法声明,也被称为
方法覆盖
,方法复写
。 - 使用特点:
- 如果方法名不同,就调用对应的方法
- 如果方法名相同,最终使用的是子类自己的
- 方法重写的应用:
- 当子类需要父类的功能,而功能主体子类有自己特有内容时,可以重写父类中的方法,这样,即沿袭了父类的功能,又定义了子类特有的内容。
方法重写的注意事项
- 父类中私有方法不能被重写
- 子类重写父类方法时,访问权限不能更低
- 父类静态方法,子类也必须通过静态方法进行重写。(其实这个算不上方法重写,但是现象确实如此,至于为什么算不上方法重写,多态中会讲解)
class Phone {
public void call(String name) {
System.out.println("给"+name+"打电话");
}
}
class NewPhone extends Phone {
public void call(String name) {
//System.out.println("给"+name+"打电话");
super.call(name);
System.out.println("可以听天气预报了");
}
}
class ExtendsDemo9 {
public static void main(String[] args) {
NewPhone np = new NewPhone();
np.call("林青霞");
}
}
练习题
- Eg1:方法重写和方法重载的区别?方法重载能改变返回值类型吗?
方法重写(Override)
:- 在子类中,出现和父类中一模一样的方法声明的现象。
方法重载(Overload)
:- 同一个类中,出现的方法名相同,参数列表不同的现象。
方法重载能改变返回值类型,因为它和返回值类型无关。
- 同一个类中,出现的方法名相同,参数列表不同的现象。
- Eg2: this关键字和super关键字分别代表什么?以及他们各自的使用场景和作用。
this
:代表当前类的对象引用super
:代表父类存储空间的标识。(可以理解为父类的引用,通过这个东西可以访问父类的成员)- 场景:
- 成员变量:
- this.成员变量
- super.成员变量
- 构造方法:
- this(…)
- super(…)
- 成员方法:
- this.成员方法
- super.成员方法
- 成员变量:
- Eg3:
//定义人类
class Person {
//姓名
private String name;
//年龄
private int age;
public Person() {
}
public Person(String name,int age) { //"林青霞",27
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
//定义学生类
class Student extends Person {
public Student() {}
public Student(String name,int age) { //"林青霞",27
//this.name = name;
//this.age = age;
super(name,age);
}
}
//定义老师类
class Teacher extends Person {
}
class ExtendsTest4 {
public static void main(String[] args) {
//创建学生对象并测试
//方式1
Student s1 = new Student();
s1.setName("林青霞");
s1.setAge(27);
System.out.println(s1.getName()+"---"+s1.getAge());
//方式2
Student s2 = new Student("林青霞",27);
System.out.println(s2.getName()+"---"+s2.getAge());
//补齐老师类中的代码并进行测试。
}
}
时间: 2024-10-29 10:45:46