2021-06-16
类
- 一种抽象的数据类型,对某一类事物整体描述或定义,但不能代表某具体的事物
- 动物、植物、手机、电脑……
- Person类、Pet类、Car类等,这些类都是用来描述或定义某一类事物应具备的特点和行为
对象
- 抽象概念的具体实例
- 张三是人的一个具体实例,张三家里的旺财是狗的一个具体实例
- 能体现特点,展现功能的是具体的实例,而不是一个抽象的概念
创建与初始化对象
- 使用new关键字创建对象
- 创建时,除分配内存空间外,还会给【创建好的对象】进行默认的初始化以及对类中构造器的调用
- 类中的构造器也称为构造方法,是创建对象时必须要调用的。构造器有以下两个特点:
- 必须和类的名字相同
- 必须没有返回类型,也不能写void
- 构造器必须掌握
类实例化
package com.oop.demo02;
//学生类
public class Student {
//属性:字段
String name;//null
int age;//0
//方法
public void study(){
System.out.println(this.name+"在学习");
}
}
//学程序,对世界更好的建模!
/*
public static void main(String[] args) {
//类:抽象的,实例化
//类实例化后会返回一个自己的对象!
//student对象就是Student类的具体实例!
Student xiaoming = new Student();
Student xiaohong = new Student();
xiaoming.name = "小明";
xiaoming.age = 3;
System.out.println(xiaoming.name);
System.out.println(xiaoming.age);
System.out.println(xiaohong.name);
System.out.println(xiaohong.age);
}
*/
无参构造与有参构造
package com.oop.demo02;
//java-------class
public class Person {
//无参构造:即使什么也不写,也会存在方法
//显示的定义构造器
String name;
int age;
//alt + insert生成构造器(有参/无参)
//实例化初始值
//1、使用new关键字,本质是在调用构造器
//2、用来初始化值
public Person(){
}
//有参构造:一旦定义了有参构造,无参就必须显示定义
public Person(String name){
this.name = name;
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
}
/*
public static void main(String[] args) {
//new 实例化了一个对象
Person person = new Person("kuangshen",23);
System.out.println(person.name);
}
构造器:
1、和类名相同
2、没有返回值
作用:
1、new本质是调用构造器
2、初始化对象的值
注意点:
1、定义有参构造后,如果要使用无参构造,显示的定义一个无参的构造
快捷键Alt+Insert:生成构造器
this. = ;
*/
创建对象内存分析
package com.oop;
import com.oop.demo03.Pet;
public class Application {
public static void main(String[] args) {
/*
1、类与对象
类是模板:抽象;对象是实例:具体;
2、方法
定义、调用
3、对象的引用
引用类型:基本类型(8)
对象通过引用来操作:栈➡堆
4、属性:字段field 成员变量
默认初始化:
数字:0 0.0
char:u0000
boolean:false
引用:null
修饰符 属性类型 属性名 = 属性值
5、对象的创建和使用:
——必须使用new关键字创造对象,构造器 Person kuangshen = new Person();
——对象的属性 kuangshen.name
——对象的方法 kuangshen.sleep()
6、类
静态的属性 属性
动态的行为 方法
“封装、继承、多态”
*/
}
}
封装
- 该露的露,该藏的藏(举例:电视)
- 程序设计要追求“高内聚,低耦合”
- 高内聚:类的内部数据操作细节自己完成,不允许外部干涉
- 低耦合:仅暴露少量的方法给外部使用
- 封装(数据的隐藏)
- 通常,应禁止直接访问一个对象中数据的实际表示,而应通过操作接口来访问,称为信息隐藏
- 记住这句话就够了:属性私有,get/set
示例
package com.oop.demo04;
//类
public class Student {
//封装一般针对属性
private String name;//名字
private int id;//学号
private char sex;//性别
private int age;
//提供一些可以操作这些属性的方法!
//提供一些public的get/set方法!
//get获得属性/数据
//set给属性/数据设置值
public String getName(){
return this.name;
}
public void setName(String name){
this.name = name;
}
//Alt + Insert快捷键,生成get/set
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public char getSex() {
return sex;
}
public void setSex(char sex) {
this.sex = sex;
}
public int getAge() {
return age;
}
public void setAge(int age) {
if (age>120 || age<0){
this.age = 3;
}else{
this.age = age;
}
}
}
package com.oop;
import com.oop.demo04.Student;
/*
1、提高程序的安全性,保护数据
2、隐藏代码的实现细节
3、统一接口
4、系统可维护增加了
*/
public class Application {
public static void main(String[] args) {
Student s1= new Student();
Student s2= new Student();
String name = s1.getName();
s1.setName("秦疆");
System.out.println(s1.getName());
s1.setAge(125);
System.out.println(s1.getAge());
}
}
继承——类
- 继承的本质是对某一批类的抽象
- 关键字extends的意思是“扩展”,子类是父类的扩展
- Java中类只有单继承,没有多继承
- 继承是类和类之间的一种关系。除此之外,还有依赖、组合、聚合等关系
- 继承关系的两个类,一个为子类(派生类),一个为父类(基类)
- 子类和父类之间,从意义上讲应该具有“is a”的关系
继承示例
package com.oop.demo05;
//Student is Person子类/派生类
//子类继承父类,就会拥有父类的全部方法
public class Student extends Person {
//Ctrl + H打开继承束hierarchy
}
package com.oop.demo05;
//在java中,所有的类,都默认直接或间接继承Object
//Person父类/基类
public class Person {
//public
//protected
//default
//private
private int money = 10_0000_0000;
public void say(){
System.out.println("说了一句话");
}
//设置属性私有,但可提供方法调用
public int getMoney() {
return money;
}
public void setMoney(int money) {
this.money = money;
}
}
-
object类
在java中,所有的类,都默认直接或间接继承Object
-
super类
-
方法重写(重点!!!)重写➡多态
this和super
super注意点:
1、super用于调用父类的构造方法,必须在构造器的第一个
2、super必须出现在子类的方法或构造方法中
3、super和this不能同时调用构造方法
VS this
代表的对象不同:
this本身调用者这个对象
super代表父类对象的应用
前提:
this没有继承也可以使用
super只能在继承条件下才可以使用
构造方法:
this();本类的构造
super();父类的构造
示例1
package com.oop.demo05;
//在java中,所有的类,都默认直接或间接继承Object
//Person父类/基类
public class Person {
protected String name = "kuangshen";
}
package com.oop.demo05;
//Student is Person子类/派生类
//子类继承父类,就会拥有父类的全部方法
public class Student extends Person {
private String name = "qinjiang";
public void test(String name){
System.out.println(name);//秦疆
System.out.println(this.name);//qinjiang
System.out.println(super.name);//kuangshen
}
}
package com.oop;
import com.oop.demo05.Person;
import com.oop.demo05.Student;
public class Application {
public static void main(String[] args) {
Person person = new Person();
Student student = new Student();
student.test("秦疆");
}
}
示例2
package com.oop.demo05;
//在java中,所有的类,都默认直接或间接继承Object
//Person父类/基类
public class Person {
protected String name = "kuangshen";
public void print(){
System.out.println("Person");
}
}
package com.oop.demo05;
//Student is Person子类/派生类
//子类继承父类,就会拥有父类的全部方法
public class Student extends Person {
private String name = "qinjiang";
public void print(){
System.out.println("Student");
}
public void test1(){
print();//Student
this.print();//Student
super.print();//Person
}
public void test(String name){
}
}
package com.oop;
import com.oop.demo05.Person;
import com.oop.demo05.Student;
public class Application {
public static void main(String[] args) {
Person person = new Person();
Student student = new Student();
// student.test("秦疆");
student.test1();
}
}
父类必须有一个无参构造,如果父类没有,子类也不会有无参构造;有参调有参,无参调无参
重写——方法
示例
package com.oop.demo05;
//重写是方法的重写,和属性无关
public class B {
public void test(){
System.out.println("B=>test()");
}
}
package com.oop.demo05;
//A继承了B
public class A extends B {
//override重写
@Override//注解,有功能的注释
public void test() {
System.out.println("A=>test()");
}
}
package com.oop;
import com.oop.demo05.A;
import com.oop.demo05.B;
public class Application {
//静态方法和非静态方法的区别很大
//静态方法:调用只和左边定义的数据类型有关
//非静态方法:重写
public static void main(String[] args) {
A a = new A();
a.test();//调用A类
//父类的引用指向了子类
B b = new A();//子类重写了父类的方法
b.test();//调用B类
}
}
/*
重写:先有继承关系,子类重写父类的方法
1、方法名相同
2、参数列表相同
3、修饰符,范围可以扩大,但不能缩小;public>protected>default>private
4、抛出的异常,范围可以缩小,但不能扩大;ClassNotFoundException(小)--->Execption(大)
重写:子类的方法和父类必须一致,方法体不同!
为什么需要重写?
1、父类的功能子类不一定需要,或不一定满足
2、Alt+Insert override
*/
多态——方法
- 动态编译,类型,可扩展性
- 即同一方法可以根据发送对象的不同而采用多种不同的行为方式
- 一个对象的实际类型是确定的,但可以指向对象的引用类型有很多
- 多态存在的条件
- 子类和父类有继承关系
- 子类重写父类方法
- 父类引用指向子类对象
- 注意:多态是方法的多态,属性没有多态性
- instanceof(类型转换)引用类型
多态示例
package com.oop.demo06;
public class Person {
public void run(){
System.out.println("run");
}
}
/*
多态注意事项:
1、多态是方法的多态,属性没有多态
2、父类和子类,有联系才能转换
3、转换异常,ClassCastException
4、多态存在的必要条件:继承关系,方法需要重写,父类引用指向子类
不能重写,就没有多态:
1、static方法,属于类,它不属于实例
2、final常量
3、private方法
*/
package com.oop.demo06;
public class Student extends Person{
@Override
public void run() {
System.out.println("son");
}
public void eat(){
System.out.println("eat");
}}
package com.oop;
import com.oop.demo06.Person;
import com.oop.demo06.Student;
public class Application {
public static void main(String[] args) {
//一个对象的实际类型是确定的
//new Student();
//new Person();
//可以指向的引用类型就不确定了:父类的引用指向了子类
//子类能调用的,都是自己的或继承自父类的全部方法
Student s1 = new Student();
//父类,可以指向子类,但不能调用自己没有子类独有的方法
Person s2 = new Student();
Object s3 = new Student();
//对象能执行哪些方法,主要取决于左边的类型,和右边关系不大
//未重写按父类,重写后按子类
s2.run();
s1.run();
((Student)s3).eat();//强制转换,高转低
}
}
类型转换
package com.oop.demo06;
public class Person {
public void run(){
System.out.println("run");
}
}
package com.oop.demo06;
public class Student extends Person{
public void go(){
System.out.println("go");
}
}
package com.oop;
import com.oop.demo06.Person;
import com.oop.demo06.Student;
import com.oop.demo06.Teacher;
public class Application {
public static void main(String[] args) {
//类型之间的转换:父 | 子
//子类转换为父类,可能会丢失一些子类里的方法
//高 低
Person obj = new Student();
//student.go();报错是因为student对象是Person类型 ,go方法是Student类型里的
//将student这个对象从Person类型转换为Student类型,就可以使用go方法了
Student student = (Student) obj;
//两者相同
student.go();
((Student) obj).go();
}
}
/*
1、父类引用指向子类的对象
2、子类转换为父类,向上,可能丢失一些子类里的方法(学生肯定是人)
3、父类转换为子类,向下,强制转换(人不一定是学生)
4、使得方法便于调用,减少重复的代码,更简洁
封装、继承、多态 多态类、接口
*/