目录
一个类的构造方法的作用是什么?若一个类没有声明构造方法,该程序能正确执行吗 ?为什么?
在调用子类构造方法之前会先调用父类没有参数的构造方法,其目的是?
Java面向对象(day1)
1.类,对象,引用
1.1 类
- 类是具有相同属性和行为的对象的集合。
- 类定义了该类型对象的数据结构, 称之为“成员变量”,同时也定义了一些可以被调用的功能,称之为“方法”。
- 类是用于构建对象的模板,对象的实质就是内存中的一块存储区域,其数据结构由定义它的类来决定。
- 定义类
- 类的成员变量
- 类的成员方法
public class Point {
//类型的特征(属性,成员变量)
int x;
int y;
//功能(方法,能做什么)
public void up(){ //public :公开的方法, void 表示方法无返回值,up()表示方法无参
y++;//纵坐标加1
}
1.2 对象
- 当一个类的定义存在后, 可以使用 new 运算符创建该类的对象。
- 对象创建的过程一般称为类的实例化
- 语法规则:
new 类名();
- 成员变量的初始化
对象创建之后,其成员变量可以按照默认的方式初始化,对象成员具有默认值。
成员变量的默认初始化值规则
- 成员变量的调用
成员变量的调用,可以根据某个对象的引用,找到成员变量,然后使用成员变量。
// 1. 创建一个汽车
Car car = new Car() ; // 创建的对象,赋值给引用类型的变量。
// 2. 给汽车的属性赋值
car.pinPai = "BYD宋";
car.color = "红色";
car.faDongJi = "byd发动机";
car.count = 7 ;
- 成员方法的调用
方法的调用必须通过某个对象的引用。
当通过么对象的引用调用方法时,方法中涉及的成员变量就是该对象的成员变量。
Person p1 = new Person();
p1.eat("火锅");
p1.sayHello();
p1.driver();
1.3引用类型
- 除8种基本数据类型之前,用类名(接口,数组)声明的变量称为引用类型变量,简称引用。
- 引用类型变量中存储的是某个对象在内存中的地址信息。
- 引用的功能在于访问对象。
- 引用类型变量声明语法规则:
2. JVM内存结构
2.1 方法区
- 该区间用于存放类的信息。java程序运行时候,首先会通过类加载器载入类文件的字节码文件,经过解析后将其装入方法区。类的各种信息都在方法区保存。
2.2 栈内存区
- 栈用于存放程序运行过程中的局部变量。
- 引用类型的变量p ,存储在栈内存中。
2.3 堆内存区
- jvm会在其内存空间开一个称为“堆”的存储空间,这部分空间用于存储使用new关键字创建的对象。
- 创建了一个Person对象,存储在堆内存中。
3.方法的重载
- 在java语言中,允许多个方法的名称相同,但参数列表不同,称之为方法的重载(overload)。编译器在编译时,会根据其参数的不同,绑定到不同的方法。
public class OverLoadDemo {
public static void main(String[] args) {
Shape shape = new Shape();
// 圆形的面积
int r = 5;
double s = shape.area(5); //area 属于方法的重载,但是我们可以根据参数的类型和个数,找到匹配的方法
System.out.println("面积:"+s);
double area = shape.area(3,4);
//***jdk 中的方法的重载
System.out.println(1); //println方法的重载
System.out.println("hello");
System.out.println(shape); //shape引用指向的对象的内存地址
System.out.println(new Date());
int [] a = {1,2,3};
String[] strs = {"tom","alice","jack"};
Arrays.toString(strs);
Arrays.toString(a);
}
}
4.this关键字
- 在方法中可以通过this关键字表示调用该方法的对象。
- 通常在类中使用this区分成员变量和参数,如果没有歧义,可以省略this。
public class Point {
//类型的特征(属性,成员变量)
int x;
int y;
//功能(方法,能做什么)
public void up(){ //public :公开的方法, void 表示方法无返回值,up()表示方法无参
y++;//纵坐标加1
}
public void up(int y){ //方法重载
//给成员变量y赋值
//y = y;//自己给自己赋值
this.y = y ; //用this来,指代正在被操作的对象,然后访问到对象的成员变量
}
}
- 一个类可以创建多个对象(存储于堆中),但方法只有一份(存储于方法区中)。
5.null
- 引用类型变量用于存放对象的地址,可以给引用类型赋值为null,表示不指向任何对象。
- 如果某个引用类型变量为null的时候,不能访问对象,否则抛出空指针异常。
6. 构造函数
6.1定义构造方法
- 构造方法是在类中定义的方法(每个类都有构造方法):
— 构造方法的名称必须和类名相同.
— 构造方法没有返回值,但也不能写void.
- 在java语言中可以通过构造方法实现对象成员变量初始化。
6.2构造方法重载
- 为了使用方便对一个类定义多个构造方法,这些构造方法彼此参数不同,称为构造方法的重载。创建对象时,java编译器会根据不同的参数,选择不同的构造函数。
6.4 案例
- 案例1:
public class Student {
String name ;
String sex ;
int score ;
Date birth ;
public void show(){ //方法的内部能直接使用成员变量名没有和方法参数重复的情况,就可以省略this
System.out.println(this.name+":"+this.sex+":"+this.score+":"+this.birth);
System.out.println(name+":"+sex+":"+score+":"+birth);
}
public void setName(String name){
this.name=name;//通过this.name来表示,方法内部给成员变量name赋值
}
public String getName(){
return name;//neme,就是成员变量name,这里就省略了this.
}
//分数等级
public String level(){
if(this.score>=90){ //score 就是成员变量,所以可以省略this
return "A";
} else if (this.score>=80) {
return "B";
} else if (this.score>=60) {
return "C";
}
else {
return "D";
}
}
}
package oopday1;
//区分null
//引用的值是null,那么就不能调用任何的属性和方法
public class TestStudent {
public static void main(String[] args) {
//Student stu;
//System.out.println(stu);//编译错误,未初始化的对象不能直接使用
Student stu = null;
System.out.println(stu);
//stu.show();//输出学生的信息,因为stu是null ,null是什么都没有,所以程序异常:java.lang.NullPointerException
stu = new Student();//stu中保存的就是Student对象的内存地址
System.out.println(stu);//oopday1.Student@4554617c :包名 , 类型 , @ 16进制的整数
//stu的初始数据值:name (null),sex(null) date(null),score(0)
//给成员变量赋值
stu.score=88;
//调用学生对象的方法
stu.setName("小红");
stu.show();
String res= stu.level();
System.out.println(res);
}
}
- 案例2:
public class Person {
//类的成员变量:
String name;
String sex;
int age;
double money;
//1.定义一个无参的构造函数
public Person(){
System.out.println();
}
//2.定义两个参数的构造函数
public Person(String name,String sex){
this.name = name;
this.sex = sex;
}
public Person (String name, String sex,int age,double money){
this.name = name;
this.sex = sex;
this.age= age;
this.money = money;
}
//3.定义四个参数的构造函数
//类的成员方法
//*** 无参的方法,调用时不需要传入参数
public void intro(){
System.out.println("我是"+name+",是一个"+sex+",今年"+age+"岁"+",我的存款:"+money);
}
//***有参的方法,调用这个方法的时候,传入实际参数
public void eat(String food){
System.out.println("我正在吃"+food);
}
}
public class TestPerson {
public static void main(String[] args) {
//1.创建对象并赋值给同类型的引用
Person p1 = new Person();//name,sex 都是null,age是0.money是0.0
//2.给对象属性赋值
p1.name="alice";
p1.sex="女生";
p1.age=23;
p1.money=20000.0;
//3.调用Person的方法
p1.intro();
p1.eat("包子");
//4.练习,创建一个person对象,然后修改属性值:小红,男生,19,3000 输出自我介绍,吃油条
Person p2= new Person();
p2.name="小红";
p2.sex="男生";
p2.age=19;
p2.money=3000.0;
p2.intro();
p2.eat("油条");
Person person1 = new Person();
Person person2 = new Person("小明","男");
Person person3 = new Person("小明","男",19,3000.0);
System.out.println("person1:"+person1.name+":"+person1.sex+":"+person1.age+":"+person1.money);
System.out.println("person2:"+person2.name+":"+person2.sex);
System.out.println("person3:"+person3.name+":"+person3.sex+":"+person3.age+":"+person3.money);
}
}
Java面向对象(day2)
1.继承
- extends关键字可以实现类的继承
- 子类(sub class) 可以继承父类(super class)的成员变量及成员方法。同时也可以定义自己的成员变量和成员方法。
- java语言不支持多继承,一个类只能继承一个父类。 但一个父类可以有多个子类。
案例:
import java.util.Date;
//动物类型 :公共的成员变量 公共的成员方法
// 颜色 ,生日,性别 ,脚的数量 叫, 吃 ,跑
//鸡类 : 飞
//狗类 : 看门
//**java规定,一个Java文件只能有一个公开类,并且这个公开类的名字必须和Java文件名相同
public class Animal {
String color;//颜色
Date birth;//生日
String sex;//性别
int count;//脚的数量
public void sing(String sing){
System.out.println("唱"+sing);
}
public void eat(String food){
System.out.println("吃:"+food);
}
public void run(){
System.out.println("到处跑");
}
}
/* Chicken 这个类型,只有一个成员方法
class Chicken {
public void fly(){
System.out.println("飞");
}
}
*/
//Chicken 继承了Animal中的所有成员变量和成员方法,同时也有自己独有的fly方法
class Chicken extends Animal{
public void fly(){
System.out.println("飞");
}
}
//Dog 继承了Animal中的所有成员变量和成员方法,同时也有自己独有的seeDoor方法
class Dog extends Animal{
public void seeDoor(){
System.out.println("保护家园");
}
}
2.向上造型
- 一个子类的对象可以向上造型为父类的类型
Father f = new Sun();
- java编译器编译的时候根据父类型检查调用的成员变量和成员方法是否匹配。
案例:
// 3. 向上造型 : 子类对象,赋值给父类的引用
Animal dog = new Dog() ;//
dog.birth = new Date();
dog.color = "黄色";
dog.count = 4 ;
dog.sex = "女";
dog.sing("汪汪。。。。");
dog.eat("狗粮......");
dog.run();
// dog.seeDoor() ;// 编译错误: 在编译的时候, dog引用是按引用的类型Animal使
用。 Animal没有seeDoor的方法
// 在运行的时候, dog引用找到的是对象的实际类型Dog ,进行使
用,这个时候就有seeDoor方法。
// 如果一定要调用seeDoor() , 这里只能修改dog的引用类型为Dog. ,即: Dog dog
= new Dog();
3.instanceof关键字
- 对于一个父类的引用类型,可以指向该类的对象也可以指向其任意一个子类型的对象。
- 通过instanceof 关键字判断引用指向的对象的实际类型。
- 根据引用指向的实际类型,将引用强制转换为实际类型。
// 4. 创建Animal : 动物是动物 , 狗是动物 , 鸡是动物。
Animal a1 = new Animal() ;
Animal a2 = new Dog(); // Dog 和Chicken都是Animal的子类。
Animal a3 = new Chicken() ;
// 5. 类型转换 :
// instanceof : 用于判断 引用 对应的对象是否为某种类型 , 是结果为true ,否
则结果为false.
// a2是动物 , 但是a2本质是狗。 a2不能转换为鸡这个类型。
if(a2 instanceof Dog){ // instanceof的运算结果是true或者false.
// a2 是 Dog , 那么就可以把a2转换为Dog ,然后赋值给Dog类型的引用.
Dog dog1 = (Dog) a2;
dog1.seeDoor(); // 类型转换之后,就可以调用到子类Dog的所有方法。
}
if(a3 instanceof Chicken){
Chicken chicken = (Chicken) a3;
chicken.fly();
}
Chicken chicken = (Chicken) a2; // 没有编译错误。 有运行错误:
ClassCastException - 类型转换错误。
/*
Exception in thread "main" java.lang.ClassCastException: oopday2.Dog
cannot be cast to oopday2.Chicken
at oopday2.TestAnimal.main(TestAnimal.java:51)
*/
4.继承中的构造方法
- 子类的构造方法中必须通过super调用父类的构造方法。因为创建子类之前,必须先创建父类。
- 子类的构造函数如果没有直接使用super调用父类构造方法,java编译器会自动的加入对父类无参构造函数的调用(那么要求父类必须有无参构造方法)
import javafx.beans.binding.DoubleExpression;
// 图形
public class Shape {
int x ;
int y ;
public Shape(){ // 无参构造器函数
System.out.println("Shape的无参构造函数被调用");
}
public Shape(int x , int y){
this.x = x ;
this.y = y ;
System.out.println("Shape的有参构造函数被调用");
}
public double area(){ // 成员函数
System.out.println("Shape的area函数被调用");
return 0 ;
}
}
class Rect extends Shape{
double w ;
double h ;
public Rect(){
super(); // 调用父类的无参构造函数 , 如果要写只能写在构造器函数内部的第一行。
//super(); -- 构造器函数内部,会调用父类型的构造器函数。 如果没有写super() ;
那么编译器会主动添加super().
System.out.println("Rect的无参构造函数被调用");
}
public Rect(int x , int y ){
super(x , y); // 这里就表示调用父类型的有两个参数的构造器函数。
System.out.println("Rect的有两个参构造函数被调用");
}
public Rect(int x , int y , double w , double h){
// 第一行这里隐藏了super() .
this.x = x;
this.y = y ; // this.x = x ; this.y = y 这里两句可以简化为super(x, y)
this.w = w ;
this.h = h ;
System.out.println("Rect的有四个参构造函数被调用");
}
public Rect(double w , double h){
//super(w,h); // 编译错误: super调用父类的构造器,必须是一个父类存在的。
}
// 重写:方法签名(方法的修饰符 , 返回值类型, 方法名,参数等)和父类的方法完全一致。
public double area(){
System.out.println("Rect中的area函数被调用。");
return w * h ;
}
public double area(double w , double h ){
return w * h ;
}
}
5.方法重写(overwrite)
- 子类从父类继承的方法,如果不能满足子类的需要,可以重写父类的方法。即方法名和参数列表和父类保持完全一致,方法的实现不同