方法的调用
静态方法 非静态方法
形参和实参
值传递和引用传递
this关键字
//学生类
public class Student { //注意类名应该与文件名相同,否则会报错
//非静态方法
public void say(){
System.out.println("学生说话了");
}
//静态方法
public static void say1(){
System.out.println("学生没有说话");
}
}
public class demo9 {
//main方法
public static void main(String[] args) {
//静态类,可以直接调用
Student.say1();//输出学生没有说话
//通过实例化类new,来调用非静态方法,要创建对象
//对象类型 对象名=对象值;
Student student = new Student();//alt+ctrl补全
student.say();//输出学生说话了
//调用add方法,由于是非静态的,所以要实例化之后才能调用
demo9 demo9 = new demo9();
//实参要形参类型对应
int c=demo9.add(1,2);//实参
System.out.println(c);
//值传递和引用传递
int a=1;
System.out.println(a);//输出1
demo9.change(a);
System.out.println(a);//输出1
Person person = new Person();
System.out.println(person.name);//输出null
demo9.change2(person);
System.out.println(person.name);//输出xiaoba
}
//修饰符 返回类型 方法名(参数){方法体}
//return代表方法结束,当返回值为void时,为return;
public String sayHello(){
return "Hello";
}
//静态方法 static
public static void a(){
//b();//此处调用b()会报错,因为static表示和类一起加载的,类存在时就已经存在了
//非静态表示在对象创建之后才存在,即类实例化之后才存在
}
//非静态方法
public void b(){
}
//形参
public int add(int a,int b){
return a+b;
}
//值传递和引用传递
public static void change(int a){ //返回值为空
a=10;
}
public static void change2(Person person){
person.name="xiaoba";
}
}
//引用传递:对象,本质还是值传递
//定义了一个Person类,有一个属性name
class Person{
String name;//默认值为null
}
类与对象的关系
类是一种抽象的数据类型,它是对某一类事物的整体描述/定义,但是不能代表某一个具体的事物
对象是抽象的具体实例
创建与初始化对象
使用new创建对象时,除了分配内存空间之外,还会对创建好的对象进行默认的初始化以及对类中构造器的调用
package oop;
public class Student2 {
//属性
String name;
int age;
//方法
public void study(){
System.out.println(this.name+"在学习");//this表示当前这个类
}
}
package oop;
//一个项目应该只存在一个main方法,是唯一的入口
public class Application {
public static void main(String[] args) {
//实例化类,实例化之后会返回一个自己的对象
//对象是该类的具体实例
Student2 xiaoming = new Student2();
Student2 xiaohong = new Student2();
System.out.println(xiaoming.name);//会输出null,默认值
System.out.println(xiaoming.age);//输出0
xiaoming.name="小明";
xiaoming.age=12;
System.out.println(xiaoming.name);//输出小明
System.out.println(xiaoming.age);//输出12
}
}
类中的构造器也叫做构造方法,是在进行创建对象的时候必须要调用的
构造器必须和类的名字相同
必须没有返回类型,也不能写void
作用:1.new本质是在调用构造方法 2.初始化对象的值
注意点:在定义有参构造之后,如果想使用无参构造,要显式定义无参构造
package oop;
public class Person2 {
}
ckage oop;
//一个项目应该只存在一个main方法,是唯一的入口
public class Application {
public static void main(String[] args) {
/*//实例化类,实例化之后会返回一个自己的对象
//对象是该类的具体实例
Student2 xiaoming = new Student2();
Student2 xiaohong = new Student2();
System.out.println(xiaoming.name);//会输出null,默认值
System.out.println(xiaoming.age);//输出0
xiaoming.name="小明";
xiaoming.age=12;
System.out.println(xiaoming.name);//输出小明
System.out.println(xiaoming.age);//输出12*/
//实例化了一个对象
Person2 person2 = new Person2();//此时在main中实例化一个对象,即使该类中什么都没有做
//然后运行(注意一定要运行,不然不会出现Person2的.class文件),在项目结构中确认,打开out
//文件夹中的的Person2的.class文件,可以发现Person2类里面有了一个同名的Person2的方法,且
//该方法没有返回值---所以一个类即使什么都没有,也会存在一个 方法
}
.class文件
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
package oop;
public class Person2 {
public Person2() {
}
}
package oop;
public class Person2 {
//显示定义构造器
String name;
//构造器的作用:1.实例化初始值
public Person2(){ //无参构造
this.name="xiaoba";
}
//2.使用new关键字,本质是在调用构造器(一旦定义了有参构造,无参构造必须显示定义,即必须写出代码)
public Person2(String name){ //有参构造
this.name=name;
}
//alt+insert生成构造器
}
package oop;
//一个项目应该只存在一个main方法,是唯一的入口
public class Application {
public static void main(String[] args) {
/*//实例化类,实例化之后会返回一个自己的对象
//对象是该类的具体实例
Student2 xiaoming = new Student2();
Student2 xiaohong = new Student2();
System.out.println(xiaoming.name);//会输出null,默认值
System.out.println(xiaoming.age);//输出0
xiaoming.name="小明";
xiaoming.age=12;
System.out.println(xiaoming.name);//输出小明
System.out.println(xiaoming.age);//输出12*/
//实例化了一个对象
Person2 person2 = new Person2();//此时在main中实例化一个对象,即使该类中什么都没有做
//然后运行(注意一定要运行,不然不会出现Person2的.class文件),在项目结构中确认,打开out
//文件夹中的的Person2的.class文件,可以发现Person2类里面有了一个同名的Person2的方法,且
//该方法没有返回值---所以一个类即使什么都没有,也会存在一个 方法
System.out.println(person2.name);//输出xiaoba(若没有用构造器初始化,则会输出null)
Person2 person3 = new Person2("xiaoming");
System.out.println(person3.name);//输出xiaoming
}
}
对象的属性 person.name
对象的方法 person.sleep( )
创建对象内存分析
对象是通过引用来操作的,引用是指向对象的地址,从栈指向堆,真实操作的是堆,只是用的是栈里面一个简单的引用
类:静态的属性 属性
动态的行为 方法
封装
程序设计要追求:高内聚,低耦合
高内聚是类的内部数据操作细节自己完成,不允许外部干涉
低耦合是仅暴露少量的方法给外部使用
属性私有,get/set
封装的作用:1.提高程序的安全性,保护数据
2.隐藏代码的实现细节
3.统一接口
4.系统可维护性增加了
package oop;
public class Student3 {
//属性私有
//名字
private String name;
//学号
private int id;
//性别
private char sex;
//提供一些可以操作属性的方法
//提供一些public的get/set方法
//get获得这个数据
public String getName(){
return this.name;
}
//set给这个数据设置值
public void setName(String name){
this.name=name;
}
//用alt+Fn+insert自动生成构造函数
public int getId() {
return id;
}
public void setId(int id) {
//在这里可以做安全性检查,判断用户输入的数据是否合理,如果不合理,就不会将它赋给私有属性
this.id = id;
}
}
package oop;
//一个项目应该只存在一个main方法,是唯一的入口
public class Application {
public static void main(String[] args) {
/*//实例化类,实例化之后会返回一个自己的对象
//对象是该类的具体实例
Student2 xiaoming = new Student2();
Student2 xiaohong = new Student2();
System.out.println(xiaoming.name);//会输出null,默认值
System.out.println(xiaoming.age);//输出0
xiaoming.name="小明";
xiaoming.age=12;
System.out.println(xiaoming.name);//输出小明
System.out.println(xiaoming.age);//输出12*/
//实例化了一个对象
/*Person2 person2 = new Person2();//此时在main中实例化一个对象,即使该类中什么都没有做
//然后运行(注意一定要运行,不然不会出现Person2的.class文件),在项目结构中确认,打开out
//文件夹中的的Person2的.class文件,可以发现Person2类里面有了一个同名的Person2的方法,且
//该方法没有返回值---所以一个类即使什么都没有,也会存在一个 方法
System.out.println(person2.name);//输出xiaoba(若没有用构造器初始化,则会输出null)
Person2 person3 = new Person2("xiaoming");
System.out.println(person3.name);//输出xiaoming*/
//封装
Student3 student3 = new Student3();
//student3.name报错,因为name是私有的
student3.setName("xiaoba");
String name3=student3.getName();
System.out.println(name3);
student3.setId(21);
System.out.println(student3.getId());
}
}
继承
继承的本质是对某一批类的抽象,从而实现对现实世界的更好的建模
Java中类只有单继承,没有多继承
子类是父类的扩展
继承是类和类之间的一种关系,除此之外,类和类之间的关系还有依赖、组合、聚合等
object类
super
方法重写
super注意点:
1.super调用父类的构造方法,必须在构造方法的第一个
2.super必须只能出现在子类的方法或构造方法中(不能直接放在class中)
3.super和this不能同时调用构造方法
对比this:
代表的对象不同:this本身调用者这个对象
super代表父类对象的引用
前提不同:this没有继承也可以使用
super只能在继承条件下才可以使用
构造方法:this调用本类的构造
super调用父类的构造
package oop;
//父类
public class Person3 {
public int money=1;
public static void say(){
System.out.println("说话");
}
private int house=2;//私有的无法被继承
protected String name="wusaqi";
public void print(){
System.out.println("fulei");
}
//私有的无法被继承
private void add(){
}
public Person3() {
System.out.println("无参构造器");
}
//super.print();报错,因为super只能出现在子类的方法或构造方法中
}
package oop;
//学生 is 人 子类(派生类)
//注意继承和组合的区别,组合是在类中包含另一个类的对象
public class Student4 extends Person3{//学生继承了人的东西
//子类继承父类,就会拥有父类的全部方法
//ctrl+H显示继承的结构
//在Java中,所有的类都默认直接或间接继承Object(可以省略)
protected String name="jiyi";
public void test(String name){
System.out.println(name);//输出参数nam
System.out.println(this.name);//输出jiyi
System.out.println(super.name);//输出父类中的name,访问父类
print();//调用子类
this.print();//调用子类,this明确指出是自己的子类的
super.print();//调用父类
//super.add();add()为私有,不可被继承
}
public Student4() {
System.out.println("子类的无参构造器");
}
public void print(){
System.out.println("zilei");
}
}
package oop;
//一个项目应该只存在一个main方法,是唯一的入口
public class Application {
public static void main(String[] args) {
/*//实例化类,实例化之后会返回一个自己的对象
//对象是该类的具体实例
Student2 xiaoming = new Student2();
Student2 xiaohong = new Student2();
System.out.println(xiaoming.name);//会输出null,默认值
System.out.println(xiaoming.age);//输出0
xiaoming.name="小明";
xiaoming.age=12;
System.out.println(xiaoming.name);//输出小明
System.out.println(xiaoming.age);//输出12*/
//实例化了一个对象
/*Person2 person2 = new Person2();//此时在main中实例化一个对象,即使该类中什么都没有做
//然后运行(注意一定要运行,不然不会出现Person2的.class文件),在项目结构中确认,打开out
//文件夹中的的Person2的.class文件,可以发现Person2类里面有了一个同名的Person2的方法,且
//该方法没有返回值---所以一个类即使什么都没有,也会存在一个 方法
System.out.println(person2.name);//输出xiaoba(若没有用构造器初始化,则会输出null)
Person2 person3 = new Person2("xiaoming");
System.out.println(person3.name);//输出xiaoming*/
/*//封装
Student3 student3 = new Student3();
//student3.name报错,因为name是私有的
student3.setName("xiaoba");
String name3=student3.getName();
System.out.println(name3);
student3.setId(21);
System.out.println(student3.getId());*/
//继承
Student4 student4 = new Student4();
student4.say();
System.out.println(student4.money);//输出的是从父类中继承的
//System.out.println(student4.house);报错,因为house在父类中是私有的
student4.test("qqwe");
//继承:无参构造器
Student4 student5 = new Student4();
//首先执行父类的无参构造器,然后执行子类的无参构造器,且若显式写出,要写调用父类的构造在子类的的前面
}
}
重写
package oop;
public class B {
public static void trying(){
System.out.println("B--trying");
}
public void trying2(){
System.out.println("B--trying2");
}
}
package oop;
//重写都是方法的重写,和属性无关
public class A extends B{
public static void trying(){
System.out.println("A--trying");
}
public void trying2(){
System.out.println("A--trying2");
}
}
//重写
A a = new A();
a.trying();//输出A--trying
B b=new A();//父类的应用指向了子类
b.trying();//输出B--trying
//方法的调用只和左边,即定义的数据类型有关
//静态和非静态方法区别很大
//重写只和非静态有关,和静态方法无关,且重写只能是public
A a2 = new A();
a2.trying2();//输出A--trying2
B b2=new A();//子类重写了父类的方法
b2.trying2();//输出A--trying2
重写:需要有继承关系,子类重写父类的方法(只能重写方法,不能重写属性)
1.方法名必须相同
2.参数列表必须相同
3.修饰符:范围可以扩大,但是不能缩小 public>protected>default> private
4.可能会抛出异常:范围可以被缩小,但不能扩大 ClassNotFoundException-->Exception
重写:子类的方法和父类必须一致,方法体不同
alt+Fn+insert选中重写:override
为什么需要重写?
1.父类的功能,子类不一定需要,或者不一定满足,需要对一些方法进行重写
多态
动态编译:可扩展性
即同一方法可以根据发送对象的不同而采用多种不同的行为方式
一个对象的实际类型是确定的,但可以指向对象的引用的类型有很多(父类或有关系的类)
多态注意事项:
1.多态是方法的多态,属性没有多态
2.父类和子类有联系,不能将一个String类型转换为一个Person类型,有父子之间的关系才能转换,类型转换异常ClassCastException
3.存在的条件:继承条件,方法需要重写,父类引用指向子类对象 father f1=new son();
哪些方法不能被重写?
1.static方法,属于类,不属于实例
2.final修饰的,常量,无法改变
3.private修饰的,私有
//父类
public class Person3 {
//多态
public void run(){
System.out.println("run");
}
}
//学生 is 人 子类(派生类)
//注意继承和组合的区别,组合是在类中包含另一个类的对象
public class Student4 extends Person3{//学生继承了人的东西
//子类继承父类,就会拥有父类的全部方法
//ctrl+H显示继承的结构
//在Java中,所有的类都默认直接或间接继承Object(可以省略)
//多态
/* @Override //重写
public void run() {
System.out.println("son");
}*/
public void eat(){
System.out.println("eat");
}
}
//多态
//一个对象的实际类型是确定的,可以指向的引用类型不确定
Student4 student6 = new Student4();
Person3 student7 = new Student4();//父类的引用指向子类
//Object student8 = new Student4();也可以
//String student9=new Student4();会报错,有父子之间的关系才能转换,不是任意一个类型都可以随意转换
student7.run();//当子类Student4中没有重写run时,输出run;当子类重写了父类的方法,会执行子类的方法
student6.run();//输出son
student6.eat();//输出eat
//student7.eat();不能这样直接调用eat(),会报错,因为student7的类型为Person3,Person3中没有eat()方法
//但当子类和父类都有的情况下,只要子类没有重写父类,就调用父类的;如果子类重写了父类,就调用子类
//对象能执行哪些方法只要看对象左边的类型,和右边关系不大
//父类型的student7虽然可以指向子类,但是不能调用父类独有的方法
((Student4)student7).eat();//将students7强制转换为Students类型,高转低
父类引用指向子类的对象,子类的引用不能指向父类的对象
把子类转换为父类,向上转型,不用强制转换,可以直接转换过去
把父类转换为子类,向下转型,需要强制转换
方便方法的调用,可以使代码变得简洁
public class Student4 extends Person3{//学生继承了人的东西
//intanceof
public void go(){
System.out.println("go");
}
}
//instanceof
//Object>Person>Student4
//Object>Person>Teacher
//Object>String
Object o=new Student4();//#注意会调用父类和子类的构造函数
System.out.println(o instanceof Student4);//true
System.out.println(o instanceof Person3);//true
System.out.println(o instanceof Object);//true
System.out.println(o instanceof Teacher);//false
System.out.println(o instanceof String);//false
Person3 person4=new Student4();
System.out.println(person4 instanceof Student4);//true
System.out.println(person4 instanceof Person3);//true
System.out.println(person4 instanceof Object);//true
System.out.println(person4 instanceof Teacher);//false
//System.out.println(person4 instanceof String);编译就报错了,因为Person和String同级
Student4 student8=new Student4();//#注意会调用父类和子类的构造函数
System.out.println(student8 instanceof Student4);//true
System.out.println(student8 instanceof Person3);//true
System.out.println(student8 instanceof Object);//true
//System.out.println(student8 instanceof Teacher);报错
//System.out.println(student8 instanceof String);报错
public class Teacher extends Person3{
}
//类型之间的转换:父 子
//高 低
Person3 q=new Student4();//new一个Student4(),直接变成Person3,低转高不需要强制转换,很自然地就转换过来了
//q.go();报错,因为Person3里面没有go方法
//将这个q转换为Student4类型
Student4 w=(Student4)q;//高转低,通过强制类型转换
w.go();//或者((Student4)q).go()
//子类转换为父类,可能丢失自己本来的一些方法
今日总结
晚上不想学了,导致没有完成任务(哭)
今天学习的内容要好好理解,明天好好整理一下