工具类
定义并且遍历一个数组
public class ArrayDemo {
public static void main(String[] args)
{
//定义数组
int[] arr = {12,44,75,123,9,54};
//需求:遍历数组
for(int x = 0;x<arr.length;x++)
{
if(x==arr.length-1)
{
System.out.print(arr[x]);
}
else
{
System.out.print(arr[x]+", ");
}
}
}
}
//如果我有多个数组都要进行遍历,那么代码的重复度就很高
//如何改进呢?用方法改进
public class ArrayDemo {
public static void main(String[] args)
{
//定义数组
int[] arr = {12,44,75,123,9,54};
//需求:遍历数组
for(int x = 0;x<arr.length;x++)
{
if(x==arr.length-1)
{
System.out.print(arr[x]);
}
else
{
System.out.print(arr[x]+", ");
}
}
//静态方法调用
//printArry(arr);
//非静态
ArrayDemo ad = new ArrayDemo();
ad.printArry(arr);
}
/*
public static void printArry(int[] arr)
{
for(int x = 0;x<arr.length;x++)
{
if(x==arr.length-1)
{
System.out.print(arr[x]);
}
else
{
System.out.print(arr[x]+", ");
}
}
}
*/
//假设这个方法不是静态的
public void printArry(int[] arr)
{
for(int x = 0;x<arr.length;x++)
{
if(x==arr.length-1)
{
System.out.print(arr[x]);
}
else
{
System.out.print(arr[x]+", ");
}
}
}
}
测试类的作用是创建其他类的对象,调用其他类的功能。而我们现在的操作是跟数组相关的,所以你应该把这些类定义到数组类中定义一个数组的操作类.
有了数组操作类之后的调用。
class ArrayTool{
//把构造方法私有外界就不能再创建对象了
//只能通过类名去访问方法
private ArrayTool(){
}
public static void printArry(int[] arr)
{
for(int x = 0;x<arr.length;x++)
{
if(x==arr.length-1)
{
System.out.print(arr[x]);
}
else
{
System.out.print(arr[x]+", ");
}
}
}
}
public class ArrayDemo1 {
public static void main(String[] args)
{
int[] arr = {12,44,75,123,9,54};
//ArrayTool at = new ArrayTool();
//at.printArry(arr);
//方法改进为静态后,就可以直接通过类名调用
ArrayTool.printArry(arr);
}
}
class ArrayTool1{
//把构造方法私有外界就不能再创建对象了
//只能通过类名去访问方法
private ArrayTool1(){
}
public static void printArry(int[] arr)
{
for(int x = 0;x<arr.length;x++)
{
if(x==arr.length-1)
{
System.out.print(arr[x]);
}
else
{
System.out.print(arr[x]+", ");
}
}
}
public static int getMax(int[] arr){
int max = arr[0];
for(int x = 0;x<arr.length;x++)
{
max = arr[x];
}
return max;
}
public static int getIndex(int[] arr,int value)
{
int index = -1;
for(int x = 0;x<arr.length;x++)
{
if(arr[x]==value)
{
index = x;
break;
}
}
return index;
}
}
public class ArrayDemo2 {
public static void main(String[] args)
{
int[] arr = {12,44,75,123,9,54};
//ArrayTool at = new ArrayTool();
//at.printArry(arr);
//方法改进为静态后,就可以直接通过类名调用
ArrayTool1.printArry(arr);
//获取最值
int max = ArrayTool1.getMax(arr);
System.out.println("max:"+max);
//获取索引值
int index = ArrayTool1.getIndex(arr, 75);
System.out.println("index:"+index);
}
}
如何制作一个说明书呢?
- 写一个工具类
- 对这个类加入文档注释
但是怎么加呢?加些什么东西呢? - 用工具解析文档注释
javadoc工具 - 格式;
javadoc -d 目录 -author -version ArrayTool.java
目录:就可以写一个文件夹的工具
制作帮助文档出错:
找不到可以文档化的公共或受保护的类:告诉我们权限不够
首先打开index文件
如何使用帮助文档
- 打开帮助文档
- 点击显示找到索引看到输入框
- 知道你要找谁?一scanner举例
- 再输入框里面输入scanner,然后回车
- 看包:java.lang包下的类不需要导入,其他的全部都要导入:
java.util.Scanner - 再简单的看看类的解释和说明,别忘了看看该类的坂本
- 看类的结构:
成员变量:字段摘要
构造方法:构造方法摘要 Constructor Summary
成员方法:方法摘要 Method Summary - 学习下构造方法
A:有构造方法 就直接创建对象
B:无构造方法 成员可能都是静态的 - 看成员方法
A:左边 是否静态:如果静态可以通过类名调用
返回值类型:人家返回什么,你就用什么接收
B:右边 看方法名:方法名称不要写错
参数列表:人家要什么,你就给什么;人家要几个你就给几个。
举例学习math方法
- 打开帮助文档
- 点击显示找到索引看到输入框
- 知道你要找谁?一Math举例
- 再输入框里面输入math,然后回车
- 看包:java.lang包下的类不需要导入,其他的全部都要导入:
- 再简单的看看类的解释和说明,别忘了看看该类的坂本
- 看类的结构:
成员变量:字段摘要
构造方法:构造方法摘要 无,发现成员是静态的
成员方法:方法摘要 Method Summary
掌握一个方法:获取随机数的方法
public static double random()
Returns a double value with a positive sign, greater than or equal to 0.0 and less than 1.0. Returned values are chosen pseudorandomly with (approximately) uniform distribution from that range.
猜数字游戏案例
/*
* 猜数字的小游戏(1-100)
*/
import java.util.Scanner;
public class LittleGame {
public static void main(String[] args)
{
//程序随机产生一个随机数。被猜的。
int number = (int)(Math.random()*100+1);
//键盘录入数据(你猜的)
// System.out.println("请输入你要猜的数据(1-100):");
// Scanner sc = new Scanner(System.in);
// int guessNumber = sc.nextInt();
while(true)
{
System.out.println("请输入你要猜的数据(1-100):");
Scanner sc = new Scanner(System.in);
int guessNumber = sc.nextInt();
if(guessNumber>number)
{
System.out.println("你猜的数据"+guessNumber+"大了");
}
else if(guessNumber<number)
{
System.out.println("你猜的数据"+guessNumber+"小了");
}
else {
System.out.println("恭喜你猜对了");
break;
}
}
}
}
代码块
代码块概述
在Java中,用{}括起来的代码被称为代码块,根据其位置和声明的不同,可以分为局部代码块,构造代码块,静态代码块,同步代码块
- 局部代码块:局部位置,用于限定变量的生命周期,及早释放。
- 构造代码块:在类中的成员位置,用大括号括起来的代码,每次调用构造方法执行前,都会执行构造代码块。
作用:可以把多个构造方法中的共同代码放到一起。 - 静态代码块:在类中的成员位置,用{}括起来,只不过,他是用static修饰了。
作用:一般是对类进行初始化。
面试题:静态代码块、构造代码块、构造方法的执行顺序?
静态代码块–构造代码块 —构造方法
静态代码块:只执行一次
构造代码块:每次调用构造方法都执行。
class Code{
//静态代码块
static{
int a = 1000;
System.out.println(a);
}
//构造代码块
{
int x = 100;
System.out.println(x);
}
//构造方法
public Code(){}
//构造方法
public Code(int a){
System.out.println("code");
}
//构造代码块
{
int y = 200;
System.out.println(y);
}
//静态代码块
static{
int a = 1000;
System.out.println(a);
}
}
public 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);
System.out.println("-----");
}
}
写程序的执行结果
class Student{
static{
System.out.println("Student 静态代码块");
}
{
System.out.println("Student 构造代码块");
}
public Student(){
System.out.println("Student() 构造方法");
}
}
public class StudentDemo {
static {
System.out.println("林青霞");
}
public static void main(String[] args)
{
System.out.println("我是main方法");
Student s1 = new Student();
Student s2 = new Student();
}
//结果
// 林青霞
// 我是main方法
// Student 静态代码块
// Student 构造代码块
// Student() 构造方法
// Student 构造代码块
// Student() 构造方法
}
继承
首先来观察一段代码
class Student{
String name ;
int age;
//getXxx()/setXxx()
public Student(){
System.out.println("吃饭");
}
}
class Teacher{
String name;
int age;
public Teacher(){}
//getXxx()/setXxx()
public void eat(){
System.out.println("吃饭");
}
}
我们观察上面两个代码:
发现name,age成员变量,以及getXxx()/setXxx(),还有eat()等都是相同的。
如果我们后面继续定义类,比如说:工人类,军人类,他们是不是也具备这些内容。那么我们每一次定义这样的类的时候,都要把这些重复的内容都重新定义一遍。
很麻烦!所以我们要考虑改进。
请问如何改进呢?
我是这样想的:我能不能把这些相同的内容定义到一个独立的类中。然后,让这多个类和这个独立的类产生一个关系,有了这个关系之后,这多个类就可以具备这个独立的类的功能。
为了实现这个效果,java就提供了一个技术:继承
继承的格式与表示
格式参照:
class Fu{}
class Zi extends FU{
}
我们就回头修改我们的代码:
class Person{
String name;
int age;
public Person(){
}
//getXxx()/setXxx()
public void eat(){
System.out.println("吃饭");
}
}
class Student extends Person{
public Student(){
}
}
class Teacher extends Person{
public Teacher(){
}
}
继承的案例
- 继承概述:多个类中存中相同属性和行为是,将这些内容抽取倒单独一个类中,那么多个类无需再定义这些属性和行为,只要继承那个类既可。
- 通过extends关键字可以实现类与类的继承
class 子类名 extends 父类名{} - 单独的这个类称为父类,基类或者超类:这多个类可以成为子类,或这派生类。
- 有了继承以后,我们定义一个类的时候,可以在一个已经存在的类的基础上,还可以定义自己的新成员。
使用继承前
class Student1{
public void eat(){
System.out.println("吃饭");
}
public void sleep(){
System.out.println("睡觉");
}
}
class Teacher1{
public void eat(){
System.out.println("吃饭");
}
public void sleep(){
System.out.println("睡觉");
}
}
public class jicheng {
public static void main(String[] args)
{
Student1 s = new Student1();
s.eat();
s.sleep();
Teacher1 t = new Teacher1();
t.eat();
t.sleep();
}
}
使用继承后
class Person1{
public void eat(){
System.out.println("吃饭");
}
public void sleep(){
System.out.println("睡觉");
}
}
class Student1 extends Person1{
}
class Teacher1 extends Person1{
}
public class jicheng{
public static void main(String[] args)
{
Student1 s = new Student1();
s.eat();
s.sleep();
System.out.println("------");
}
}
好处:
- A:提高了代码的复用性
- B:提高了带妈的维护性
- C:让类与类之间产生了关系,是多态的前提
类与类产生了关系,其实也是继承类的一个弊端:
类的偶合性增强了。
开发的原则:低耦合,高内聚
耦合:类与类之间的关系
内聚:就是自己完成某件事情的能力
java中继承的特点:
- java中只支持单继承,不知此多继承(有些语言是支持多继承,格式:extends 类1,类2……)
class Father{}
class Mother{}
//会报错
class Son extends Father,Mother{
}
- java支持多层继承(继承体系)
class GrandFather{
public void show(){
System.out.println("我是爷爷");
}
}
class Father extends GrandFather{
public void method(){
System.out.println("我是老子");
}
}
class Son extends Father{}
public class ExtendsDemo2 {
public static void main(String[] args)
{
Son s = new Son();
s.show();
}
}
继承的注意事项以及继承的使用时间
注意:
* 子类不能继承父类的私有方法
class Father{
private int a = 10;
public int b = 20;
//私有方法子类不能继承
private void method(){
System.out.println(a);
System.out.println(b);
}
public void show(){
System.out.println(a);
System.out.println(b);
}
}
class Son extends Father{
}
}
public class ExtendsDemo {
public static void main(String[] args)
{
Son s = new Son();
//找不到方法,子类不能继承父类的私有方法
//s.method();
s.show();
}
}
- 子类不能继承父类的私有成员变量
class Father{
private int a = 10;
public int b = 20;
//私有方法子类不能继承
private void method(){
System.out.println(a);
System.out.println(b);
}
public void show(){
System.out.println(a);
System.out.println(b);
}
}
class Son extends Father{
public void Function(){
//子类不能继承父类的私有成员变量
System.out.println(a);
System.out.println(b);
}
}
public class ExtendsDemo {
public static void main(String[] args)
{
Son s = new Son();
//找不到方法,子类不能继承父类的私有方法
//s.method();
s.show();
s.Function();
}
}
继承类的注意事项:
A:子类只能继承父类所有非私有的成员(成员方法和成员变量)
B:子类不能继承父类的构造方法,凡是可以通过super关键字去访问父类构造方法
C:不要为了部分功能而去继承
那么我们什么时候考虑继承呢?
继承其实体现的是一种关系:“is a”。
采用假设法:如果有两个类A、B。只要他们符合A是B的一种,或者B是A的一种,就可以考虑使用继承。
继承中成员变量的关系
类的组成:
- 成员变量
- 构造方法
- 成员方法
而现在我们又讲解了继承,所以我们就应该来考虑一下,类的组成部分的各自关系。
继承中成员变量的关系:
A:子类中的成员变量和父类中的成员变量名称不一样,这个太简单
B:子类中的成员变量和父类中的成员变量名称一样,这个怎么玩
在子类中访问一个变量的查找顺序:
a:在子类方法的局部范围找,有就使用
b:在子类的成员范围找,有就使用
c:在父类的成员范围找,有就使用
d:如果还找不到,就报错
class Father{
public int num = 10;
}
class Son extends Father{
public int num2 = 20;
public int num = 20;
public void show(){
int num = 50;
System.out.println(num);
System.out.println(num2);
}
}
public class ExtendsDemo3 {
public static void main(String[] args)
{
//创建对象
Son s= new Son();
s.show();
}
}
this 和super的区别
思考一个问题:
我不仅要输出局部范围的num,还要输出本类成员范围的num。怎么办呢?
我还想要输出父类成员范围的num。怎么办呢?
如果有一个东西和this相似,但是可以直接访问父类的数据就好了。
这时候关键字super出现了。
this 和super的区别
- this 代表本类对应的引用
- super代表父类存储空间的标识(可以理解为父类引用,可以操作父类的成员)
怎么用呢?
A:调用成员变量
- this.成员变量 调用本类的成员变量
- super.成员变量 调用父类的成员变量
B:调用构造方法
- this (…) 调用本类的构造方法
- super(…) 调用父类的构造方法
C:调用成员方法
- this 成员方法 调用本类的成员方法
- super 成员方法 调用父类的成员方法
class Father1{
public int num = 10;
}
class Son1 extends Father{
public int num = 20;
public void show(){
int num = 30;
System.out.println(num);
//使用this关键字,可以输出num= 30当前类中的num
System.out.println(this.num);
//使用super关键字,可完成输出父类中的num的值。
System.out.println(super.num);
}
}
public class ExtendsDemo5 {
public static void main(String[] args)
{
Son1 s = new Son1();
s.show();
}
}
继承间的构造方法的关系
- 子类中所有的构造方法默认都会访问父类中空参数的构造方法
- 为什么子类所有的构造方法执行都回去走父类中的构造方法
- 因为子类会继承父类中的数据,可能还会使用父类的数据,所以子类初始化之前,一定要先完成父类数据的初始化。
- 每一个构造方法的第一条语句默认都是super(),没写就就默认有。
class Father2{
public Father2(){
System.out.println("Father的无参构造方法");
}
public Father2(String name){
System.out.println("Father的带参构造方法");
}
}
class Son2 extends Father2{
public Son2(){
//super();
System.out.println("Son的无参构造方法");
}
public Son2(String name){
//super();
System.out.println("Son的带参构造方法");
}
}
public interface ExtendsDemo6 {
public static void main(String[] args)
{
//创建对象
Son2 s = new Son2();
System.out.println("-------");
Son2 s2 = new Son2("林青霞");
}
}
继承构造方法的注意事项
如果父类没有无参构造方法,那么子类的构造方法会出现什么现象呢?
如何解决呢?
A:加一个无参构造方法
/*
* 如果父类没有无参构造方法,那么子类的构造方法会出现什么现象呢?
* 如何解决呢?
*/
class Father{
public Father(){
System.out.println("Father的无参构造方法");
}
public Father(String name){
System.out.println("Father的带参构造方法");
}
}
class Son extends Father{
public Son(){
System.out.println("Son的无参构造方法");
}
public Son(String name){
System.out.println("Son的带参构造方法");
}
}
public class Extends07 {
public static void main(String[] args)
{
}
}
B:通过使用Super关键字去显示的调用父类的带参构造方法
/*
* 如果父类没有无参构造方法,那么子类的构造方法会出现什么现象呢?
* 如何解决呢?
*/
class Father{
// 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的带参构造方法");
}
}
public class Extends07 {
public static void main(String[] args)
{
Son s = new Son();
Son ss = new Son("林青霞");
}
}
C:子类通过this去调用本类的其他构造方法。
/*
* 如果父类没有无参构造方法,那么子类的构造方法会出现什么现象呢?
* 如何解决呢?
*/
class Father{
// 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("随便昂");
this();
System.out.println("Son的带参构造方法");
}
}
public class Extends07 {
public static void main(String[] args)
{
Son s = new Son();
Son ss = new Son("林青霞");
}
}
注意:
子类中一定要有一个去访问了父类的构造方法,否则父类数据就没有初始化。
this(…)和super(…)调构造的时候一定要出现在第一条语句上。如果不是放在第一条语句上,就可能对父类的数据进行了多次初始化,所以必须放在第一条语句上。
继承中的面试题
看程序写结果
A:成员变量 就近原则
B:this和super的问题 this访问本类的成员 super访问父类的成员
C:子类构造方法执行前,默认先执行父类的无参构造方法。
D:一个类的初始化过程
- 成员变量进行初始化
- 默认初始化
- 显示初始化
- 构造方法初始化
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);
System.out.println(this.num);
System.out.println(super.num);
}
}
public class ExtendTest {
public static void main(String[] args)
{
Zi z = new Zi();
z.show();
}
}
结果:
Fu
Zi
30
20
10
看程序写结果:
A:
一个类的静态代码块,构造代码块,构造方法的执行流程
静态代码块>构造代码块>构造方法块
B:
静态的内容是随着类的加载而加载
静态代码块的内容会优先执行
C:
子类初始化之前先会进行父类的初始化
class Fu1{
static{
System.out.println("静态代码块Fu");
}
{
System.out.println("构造代码块Fu");
}
public Fu1(){
System.out.println("构造方法FU");
}
}
class Zi1 extends Fu1{
static{
System.out.println("静态代码块");
}
{
System.out.println("构造代码块zi");
}
public Zi1()
{
System.out.println("构造方法Zi");
}
}
public class ExtendTest3 {
public static void main(String[] args)
{
Zi1 z = new Zi1();
}
}
结果:
静态代码块Fu
静态代码块
构造代码块Fu
构造方法FU
构造代码块zi
构造方法Zi
看程序写结果:
A:成员变量的问题:
B:一个类的初始化过程:
成员变量的初始化:
- 默认初始化
- 显示初始化
- 构造方法初始化
C:子父类的初始化:先进行父类初始化,然后进行子类初始化。
class X{
Y b = new Y();
X(){
System.out.println("X");
}
}
class Y{
Y(){
System.out.println("Y");
}
}
public class Z extends X {
Y y =new Y();
Z(){
System.out.println("Z");
}
public static void main(String[] args)
{
new Z();
}
}
结果:yxyz
继承中成员的方法关系
- 子类中的方法和父类中的方法声明不一样,这个太简单
- 子类中的方法和父类中的方法声明不一样,这个该怎么玩呢?
a:先找子类中,看看有没有这个方法,如果有就使用
b:再看父类中有没有这个方法,有就使用
c:如果没有就报错。
方法重写的应用
子类中出现了和父类中方法声明一模一样的方法。
方法重载:本类中出现的方法名一样,参数列表不同的方法。与返回值无关。
使用特点:
- 如果方法名不同,就调用对应的方法
- 如果方法名相同,最终使用的是子类自己的。
子类对象调用方法的时候:先找子类本身,再找父类。
方法重写的应用:当子类需要父类的功能,而功能主体子类有自己特有的内容时,可以重写父类中的方法。这样,即沿袭了父类的功能,有定义了子类特有的内容。
//案例:
//A:定义一个手机类
//B:通过研究新手机作用是打完电话后,可以听天气预报
//但是呢,我们又发现新手机应该是继承自手机
//其实这个时候的设计并不是最好的,因为手机打电话功能,
//是手机本身就具备的最基本的功能,所以我的新手机是不用再提供这个功能
//但是这个时候打电话功能就没有了,最终还是要加上这个功能。
//由于他继承了父类,所以我们就直接使用父类的功能既可
//通过关键字super关键字调用。
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("可以听天气预报了");
}
}
public class Extenddemo2 {
public static void main(String[] args)
{
newPhone np = new newPhone();
np.call("林青霞");
}
}
方法重写的注意事项
- 父类中的私有方法不能被重写。因为父类私有方法子类根本就无法继承
- 子类重写方法时,访问权限不能更低,最好就一致。
- 父类静态方法,子类也必须通过静态方法进行重写
因此,子类重写父类方法的时候,最好一模一样。
两个面试题
1、方法重写和方法重载的区别?方法重载能改变返回值类型吗?
方法重写(Override):在子类中,出现和父类中一模一样的方法声明的现象
方法重载(Overload);同一个类中,出现的方法名相同,参数列表不同的现象。
方法重载能改变返回值的类型,因为它和返回值类型无关。
2、this关键字和super关键字分别代表什么?以及他们各自的使用场景和作用。
this:当前类的对象引用
super:代表父类存储空间的标识(可以理解为父类的引用,通过这个东西可以访问父类的成员。)
场景:
成员变量:
this.成员变量
super.成员变量
构造方法:
this(…)
Super(…)
成员方法:
this.成员方法
super.成员方法