练习:长方形类,定义一个长方形(Rectangle)类,定义求周长(length)和面积(area)的方法,然后定义一个测试类Test,进行测试。
package org.westos.MXDX;
public class Rectangle {
private double Chang;
private double Kuan;
public Rectangle() {
}
public Rectangle(double chang, double kuan) {
Chang = chang;
Kuan = kuan;
}
public double getChang() {
return Chang;
}
public void setChang(double chang) {
Chang = chang;
}
public double getKuan() {
return Kuan;
}
public void setKuan(double kuan) {
Kuan = kuan;
}
public double length() {
double i = 2 * (Chang + Kuan);
return i;
}
public double area() {
double j = Chang * Kuan;
return j;
}
}
package org.westos.MXDX;
import javax.swing.text.ChangedCharSetException;
public class MyTestRectangle {
public static void main(String[] args) {
Rectangle rec = new Rectangle();
rec.setChang(13.2);
rec.setKuan(5.7);
System.out.println(rec.getChang());
System.out.println(rec.getKuan());
System.out.println(rec.length());
System.out.println(rec.area());
System.out.println("--------------------------");
Rectangle rec1 = new Rectangle(18.3, 12.1);
System.out.println(rec1.getChang());
System.out.println(rec1.getKuan());
System.out.println(rec1.length());
System.out.println(rec1.area());
}
}
1. static 关键字
1.1 static–静态的,可以修饰成员变量和成员方法;
修饰成员变量,此变量就为一个共享变量,会被这个类的所有对象所共享
内存图:
1.2 static的特点:
a.它随着类(.class)的加载而加载,优先于对象的创建而存在的;
b.static所修饰的成员是优先于对象而存在的;
c.被类的所有对象所共享;
d.被静态所修饰的成员/变量,是属于类的,建议使用类名直接调用(当然你可以使用对象名调用,但是不推荐)
e.静态变量我们也称之为类变量
1.3 定义静态方法
a.在静态方法里面 不能调用非静态的方法 也调用不到非静态的成员
b.静态所修饰的成员,是随着类的加载而加载,是优先于对象而存在,先有的访问不到后有的,但是后有的可以调用到先有的
c.简单说 在静态方法中,只能访问静态所修饰的成员,不能访问非静态成员
d.非静态方法中,既可以访问非静态成员,也可以访问静态成员,静态只能访问静态
e.在静态方法中,不能存在this关键字,因为this本身代表一个该类的对象,是后来才有的
f.对于提供main方法作为成员入口的这个类(测试类),在这个类中,我们一般不去定义成员变量和成员方法
1.4 为什么main方法要用public static来修饰
方便虚拟机调用
1.5 成员变量和局部变量的区别(复习):
局部变量 | 成员变量 |
---|---|
方法中的变量,以及方法的形参 | 类中 方法外的变量 |
存储在栈内存 | 存储在堆内存 |
必须赋值才能使用 | 有默认值 |
属于方法,随着方法的调用而产生,随着方法的调用完毕而消失 | 属于对象,也称之为实例变量,随着对象的创建而产生,随着对象的销毁而销毁 |
1.6 静态变量和成员变量的区别:
静态变量属于类,也称之为类变量;
存在方法区的静态区;
随着类的加载而产生,随着类的卸载而卸载;
可以使用对象名调用 也可以使用类名调用,推荐使用类名调用
2. Java提供的一个类:Math
之前学过Scanner,查JDK提供的帮助文档学习—
Math类包含用于执行基本数学运算的方法;java.lang包下的类,可以不用导入包;没有构造方法,因为它的成员全部是静态的。
Math.random; // 生成随机小数(0~1之间)
// 移动代码:ctrl shift +上下键
// 生成随机整数(范围1~100,包含1和100):
int v = (int)(Math.random*10+1);
猜数字小游戏:
(不知道循环次数–用while循环)
给用户十次机会,每猜一次提示剩余次数
package org.westos.MXDX;
import java.util.Scanner;
public class guess {
public static void main(String[] args) {
int i = (int) (Math.random() * 10 + 1);
for (int j = 1; j < 11; j++) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入一个数字:");
int k = sc.nextInt();
if (k > i & j >= 0) {
System.out.println("你猜大了" + "你还有" + (10 - j) + "次机会");
} else if (k < i & j >= 0) {
System.out.println("你猜小了" + "你还有" + (10 - j) + "次机会");
} else if (k == i & j >= 0) {
System.out.println("你猜对了");
break;
} else {
System.out.println("你没有机会了");
break;
}
}
}
}
3. 代码块的概念
3.1 所谓代码块就是被一对大括号{}所括起来的代码;
3.2 分类:局部代码块,构造代码块,静态代码块,同步代码块(多线程讲)
局部代码块:定义在方法中的代码块,有利于资源的及早释放,提高内存利用率
构造代码块:定义在类中 方法外的代码块,每次在调用构造(创建对象)时,构造代码块执行,且构造代码块优先于构造方法执行
静态代码块:(用的比较多)定义在类中、方法外,并且被static所修饰的代码块,因为类只加载一次,所以只执行一次;静态代码块里面只能访问被静态所修饰的成员(优先于任何构造代码块执行)常用于准备的初始化工作
练习:看程序写结果
class Student {
static {
System.out.println("Student 静态代码块"); //3
}
{
System.out.println("Student 构造代码块"); //4 6
}
public Student() {
System.out.println("Student 构造方法");//5 7
}
}
class StudentDemo {
static {
System.out.println("StudentDemo的静态代码块"); //1
}
public static void main(String[] args) {
System.out.println("我是main方法"); //2
Student s1 = new Student();
Student s2 = new Student();
}
}
4. 继承
继承概述:
多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中,那么多个类无需再定义这些属性和行为,只要继承那个类即可。
继承格式:
通过extends关键字可以实现类与类的继承
class 子类名 extends 父类名 {}
单独的这个类称为父类,基类或者超类;这多个类可以称为子类或者派生类。
4.1 extends
作用:可以提高代码的复用性和维护性
弊端:让类和类之间产生关系,那就增加了耦合性。
程序的设计原则:高内聚(内聚:一个类能独立完成某个功能的能力),低耦合(耦合:类和类之间有一种依赖关系)
继承的特点:
a.Java只支持单继承,一个子类只能有一个父类;但是支持多层继承
b.子类只能继承父类非私有的成员(成员方法和成员变量)
c.构造方法不参与继承,但是可以通过super关键字去访问父类构造方法。
d.不要为了部分功能去继承
继承的思想:继承就是把多个子类的共性部分,向上抽取到父类当中,以实现代码的复用性和维护性
就近原则:局部变量和成员变量重名时,变量访问原则遵循就近原则:a.先在局部范围(方法内和形参),如果找到就使用,b.找不到就去该类成员范围找;如果在该类的成员范围没有找到,c.那么就去该类的父类成员范围找,d.还没有找到就报错。
// 练习:构造学生类
package org.westos.JiCheng;
public class Test {
public static void main(String[] args) {
Boys xiaoming = new Boys();
System.out.println(xiaoming.name = "小明");
System.out.println(xiaoming.age = 16);
xiaoming.KaoShi();
xiaoming.DaJia();
Girls xiaohong = new Girls();
System.out.println(xiaohong.sex = "女");
System.out.println(xiaohong.weight = 99.9);
xiaohong.TanLianAi();
xiaohong.GuoJiaJia();
}
}
class Student {
String name;
int age;
String sex;
double weight;
public void XueXi() {
System.out.println("学习");
}
public void KaoShi() {
System.out.println("考试");
}
public void TanLianAi() {
System.out.println("谈恋爱");
}
}
class Boys extends Student {
public void DaJia() {
System.out.println("打架");
}
}
class Girls extends Student {
public void GuoJiaJia() {
System.out.println("过家家");
}
}
// 练习:看程序写出执行结果(考察代码块和继承)
package org.westos.demo91;
class Fu { //Fu.class
static {
System.out.println("静态代码块Fu"); //1
}
{
System.out.println("构造代码块Fu"); //3
}
public Fu() {
System.out.println("构造方法Fu"); //4
}
}
class Zi extends Fu {
static {
System.out.println("静态代码块Zi");//2
}
{
System.out.println("构造代码块Zi"); //5
}
public Zi() {
System.out.println("构造方法Zi"); //6
}
}
class Test {
public static void main(String[] args) {
//你初始化子类的时候,先要初始化父类。
Zi z = new Zi(); //请执行结果。
}
}
4.2 super
代表父类空间的一个标识,可以认为是父类的一个对象,可以使用在子类局部范围访问父类成员变量。
this和super的区别和应用:
super | this |
---|---|
代表的是父类存储空间的标识(可以理解成父类的引用,可以操作父类的成员) | 代表本类的一个引用,你可以认为是本类的一个对象 |
super():访问父类的空参构造 | this():访问本类的空参构造 |
super.成员变量名 :访问父类的成员变量 | this.成员变量 :访问本类的成员变量 |
super.成员方法 :访问父类的成员的方法 | this.成员方法 :访问本类的成员方法 |
public class MyTest extends Object {
public static void main(String[] args) {
//Zi zi = new Zi();
Zi zi1 = new Zi("aaa", 100);
//父类的有参构造调用了aaa==100
//子类的有参构造调用了aaa==100
}
}
//Java继承体系中的顶层父类是Object类,所有类都是直接或间接继承自他
class Fu extends Object {
int num = 100;
public Fu() {
super();
System.out.println("父类的空参构造调用了");
}
public Fu(String name) {
super();
System.out.println("父类的有参构造调用了");
}
public Fu(String name, int age) {
super();
System.out.println("父类的有参构造调用了" + name + "==" + age);
}
}
class Zi extends Fu {
public Zi() {
super("abc"); //调用父类有参构造
System.out.println("子类的空参构造调用了");
}
public Zi(String str) {
// this();和super(); 不能同时存在在构造方法里面
this();//调用本类空参构造
//this("abc",23); //调用本类有参参构造
System.out.println("子类的有参构造调用了");
}
public Zi(String str, int age) {
// this();和super(); 不能同时存在在构造方法里面
super(str, age);
System.out.println("子类的有参构造调用了"+ str + "==" + age);
}
}
继承中构造方法的关系:
我们在创建子类对象时,为什么会先去调用父类的构造方法呢?—因为子类要继承或使用父类的数据,所以在初始化子类的时候,先要调用父类的构造方法,来完成父类数据的初始化,这样子类才能够继承父类的数据和使用父类的数据。
在每个类的构造方法中的第一行,有一行默认语句是super(),会去调用父类的空参构造,来完成父类数据的初始化;
Java继承体系中的顶层父类是Object类,所有类都是直接或者间接继承自它。
继承中构造方法的注意事项:
当父类没有空参构造,怎么办?想办法调用父类有参构造a: 在父类中添加一个无参的构造方法;b:子类通过super去显示调用父类其他的带参的构造方法;c:子类通过this去调用本类的其他构造方法,本类其他构造也必须首先访问了父类构造
this()和super()不能同时存在在构造方法里面
public class MyTest {
public static void main(String[] args) {
Zi zi = new Zi();
zi.show(10);
}
}
class Fu {
int num = 200;
}
class Zi extends Fu {
int num = 100;
public void show(int num) {
System.out.println(num);//10
System.out.println(this.num);//100
System.out.println(super.num);//200
}
}
4.3 方法重写
当子类出现了和父类一模一样的方法时(方法名,方法参数,返回值类型一样)这个时候会出现方法覆盖现象,子类的方法会覆盖父类的方法
为什么要有方法重写的机制:有的时候子类对父类的方法实现不是很满意,他需要扩展或者覆盖父类的方法
ctrl+o快速重写父类的方法 @Override - 注解 用来检测这个方法是不是重写父类的,如果不是就会报错
也可以在父类的基础上进行扩展 沿袭父类的功能super.call();
注意事项:
a.父类私有的方法不能重写,私有方法子类都不能继承何来重写;
b.构造方法不参与重写;
c.重写时,子类在重写父类方法时,方法的权限修饰符,不能比父类的方法低;
d.父类中的 静态方法不参与重写
e.final 修饰的方法 子类不能重写
f.子类重写父类方法的时候,最好声明一模一样。
public class MyTest {
public static void main(String[] args) {
Cat cat = new Cat();
cat.sleep();
cat.eat();
System.out.println("======================");
Dog dog = new Dog();
dog.eat();
dog.sleep();
}
}
public class Animal {
public void sleep(){
System.out.println("睡觉");
}
public void eat(){
System.out.println("吃饭");
}
}
public class Dog extends Animal{
public void eat(){
System.out.println("狗吃骨头");
}
@Override
public void sleep() {
System.out.println("狗喜欢趴着睡觉");
}
}
public class Cat extends Animal{
@Override
public void eat(){
System.out.println("猫吃鱼");
}
//Ctrl+O 重写父类的方法
@Override //@Override 注解 作用:用来检测这个方法,是不是重写父类的。
public void sleep() {
System.out.println("猫白天睡觉");
}
//@Override 不是重写的方法会报错
public void show(){
}
}
4.4 关键字:final–最终的
由于继承中有一个方法重写的现象,而有时候我们不想让子类去重写父类的方法.这对这种情况java就给我们提供了一个关键字: final,可以修饰变量、方法、类。
a. 修饰变量,此变量会变成一个常量–自定义常量,常量名一般大写
public static final int B=1000;// 公共的静态常量
修饰基本类型,指的是地址值不能被再次改变
修饰引用类型,则地址值不能被改变
b. 修饰方法,此方法不能被重写 ,可以被继承
c. 修饰类,此类不能被继承
方法重载:允许在一个域中定义多个同名方法,只要他们的参数列表不同
方法重写:要有继承关系,子类出现了和父类一模一样(参数类型 参数个数 返回值类型)的方法
package org.westos.demo94;
public class MyTest {
//自定义常量
public final int A=2000;
//公共的静态常量
public static final int B = 2000;
public static void main(String[] args) {
final int NUM=200; //自定义常量,常量名一般大写
System.out.println(MyTest.B);// 2000
final Fu fu = new Fu();
System.out.println(fu); // @1540e19d
// fu=new Fu();
// System.out.println(fu);
}
}
final class Fu{
public final void show(){
System.out.println("fu show");
}
}
/*
class Zi extends Fu{
}
*/