面向对象
基本概念
1.什么是对象
对象应该具有:属性、行为。
2.类
根据业务需要,将已有分析出来的众多对象,划分成不同的类别。定义一个class,就可以成为是一个类。
在业务分析的时候,先有对象,从对象中划分出来的类。
在编码的时候,是需要在编码上定义class,不同的类别之间总是有属性和行为上的不同。
3.类和对象之间的关系
类:对象的抽象
对象:是类的具体实现
4.类的定义
【访问权限修饰符】【修饰符】class 类名{
类体(类的成员)
}
5.类创建对象
【语法】类型 变量名(引用)=new 类名(参数)
6.方法的声明
【访问权限修饰符】【修饰符】返回值类型 方法名字(参数1,参数2…){方法体}
7.在类中其他方法(除了main)访问属性
1)在方法(main除外)访问属性:可以直接访问属性
2)如果在方法中,局部变量名字和成员变量重名
【规则】局部变量会隐藏成员变量
【解决】使用this关键字 this.成员变量名 this当前对象,谁调用谁就是当前对象
冒泡排序:稳定排序
选择排序:不稳定排序
成员变量和局部变量
变量分为成员变量和局部变量,成员变量需要来在类中声明,局部变量是在方法中
成员变量声明方式
【访问权限修饰符】【修饰符】数据类型 变量名(属性名)【=初始值】,例如String name=“张三”,可以在声明的同时进行赋值,也可以在使用(main,其他方法)之前进行赋值
访问成员变量
在main方法中,一定要有对象,才可以访问到成员:格式:对象名.属性名
成员变量和方法的内存结构
对象在堆中存储
对象中的成员变量,对于每个对象分别存储一份,存储在堆中
方法是所有的对象共享一份,存在方法区中
基本数据类型如果是局部变量,则变量名字作为数据存储区域的名,变量值直接存储在数据区域中,全部存储在栈中
成员变量 系统自动赋值
eg:string null/short 0/int 0/long0/boolean false/char /float 0.0/double0.0
boolean 赋值false(需要声明才可以,否则为空,new了后就有默认数据false)
局部成员变量 系统不自动赋值,需要自己赋值才能使用
全局变量,需要在主函数内创建类的对象,再用对象使用
基本类型:给值
引用类型:给地址,指向值
值传递和引用传递
方法参数:
值传递(参数的类型是基本数据类型,特点:不会对参数进行修改)无论是基本数据类型,还是引用类型作为参数,值传递,原则都是将栈中数据域中存储的内容传递给形式参数。如果数据域中存放的是基本数据类型,那就复制基本数据类型,如果数据域中存储的引用地址,那就将地址复制一份传递给形式参数。
引用传递(参数的类型是引用类型,特点:会对参数进行修改)相当于将引用对象的地址传递给形式参数,形式参数指向的对象和 实际参数指向的对象是同一个对象。
public class TestA {
int i ;
void change(int i){
i++;
System.out.println(i);
}
void change1(TestA t){
t.i++;
System.out.println(t.i);
}
public static void main(String[] args) {
TestA ta = new TestA();
System.out.println(ta.i); //该对象变量是0
ta.change(ta.i);//ta.0是值传递,其中int i是局部变量,改变后不影响全局变量的值,此时i0->1
System.out.println(ta.i); //0
ta.change1(ta); //1 这里是引用传递,i改变会影响全局变量
System.out.println(ta.i);//1
}
}
方法的重载
【定义】java中,如果有多个同名,但是不同参数的方法,被称为方法的重载。当实现了重载方法之后,java虚拟机执行的时候,会自动按照实际参数来分配方法。
【规则】1.定义函数名字相同
2.作用域相同
3.参数不同(数量不同,类型不同,顺序不同)
class math{
void add(int a,int b) {
System.out.println(a+b);
}
void add(int a,int b,int c) {
System.out.println(a+b+c);
}
void add(float a,int b) {
System.out.println(a+b);
}
}
可变参数
定义方法的时候,在参数中使用…代表可变参数,他讲传递过来的所有实际参数打包成数组形式
不能使用可变参数和数组类型的参数构成重载,因为可变参数的底层就是数组类型
与其他参数一起的话,可变参数要放在最后
jdk1.5之后,历史原因需要向下兼容,如果只传入一个整数类型,会调用指定的方法,不会调用可变参数的而方法
void sum(int…a)
构造器
在创建一个对象的时候,要是执行的代码块,存在的意义就是为了创建对象,可以在创建对象的同时,初始化对象中的成员变量
1.构造器的创建
【语法】【访问权限修饰符】类名(参数){构造器执行的内容}
【注意】构造器名字必须要和类名相同/没有修饰符,没有返回值
class Dog{
public String name;
public int age=11;
public Dog() {
System.out.println("这是Dog的构造器");
}
}
2.关于构造器的应用
一个类中如果没有显示的声明构造器,则编译器会自动创建一个无参数的构造器,如果显示的声明了有参数的构造器,那么编译器自动产生的无参数的构造器就失效了
3.构造器的重载
如果一个类中即希望有有参数的构造器,也希望有无参数的构造器,需要声明显示的无参数的构造器
在有参数的构造器中,可以通过参数的形式来初始化成员变量,如果是强依赖关系的属性可以通过以上方式,如果是弱以来关系的属性,在使用前在初始化成员变量
构造器调用构造器,不能直接调用构造器的名字
解决:只能通过this()关键字
【构造器调用构造器规则】
1)只能通过this(参数)关键字
2)必须位置上放在第一句话
3)必须在构造器之中调用,不能再构造器的外面调用this()
4.this关键字的作用
1)this关键字可以代表当前对象,可以在方法中调用属性
2)this关键字可以在构造器中调用其他构造器(注意,会有规则要求,放在第一句,必须使用this关键字)
3)this关键字可以代表当前对象,可以在方法中调用其他对象
static修饰符
static可以修饰成员变量,还可以修饰方法,修饰块,内部类
普通的成员变量(非静态成员变量和费静态方法)——隶属于每一个对象,每一个对象独享
【背景】new关键字可以创建对象,堆中分配内存存储,通过对象可以调用到成员变量,方法
也有时候,可能希望成员变量的方法跟每一个嗯对象无关,只跟当前的类有关,这时,可以将他们声明成static
【静态成员】包括静态成员变量和静态方法,定义的时候,直接加static关键字作为修饰符即可
【调用】通过类名就可以调用
1.static修饰成员变量(static属性)
无论有多少个对象,都跟这个static的属性无关,属性只跟当前类有关
误区:认为静态是不能修改的变量,其实所指的"静态"—是针对内存空间来说的
静态的内容是存储在方法区的静态区
static属性的定义
static 类型 变量名;
class Person{
String name;
static int count;//count可以通过类名访问
public Person(){
count++;
}
}
public class lz{
public static void main(String[] args){
Person p1=new Person();
Person p2=new Person();
System.out.println(p1.count);
System.out.println(p2.count);
System.out.println(Person.count);
}
}
比较静态变量和成员变量的区别:
1)所属不同:
静态变量:属于类,是类的属性
成员变量:属于对象,对象的变量,实例变量,实例属性
2)内存位置不同
静态变量:方法区的静态区中(多个对象公用一个变量)
成员变量:对中平,每个对象拥有一个
3)声明周期不同
静态变量:随着类的加载和加载
成员变量:随着对象的创建而创建,对象消失了,成员变量小时
4)调用方式不同
静态变量:通过类名调用,也可以通过对象名调用
成员变量:只能通过对象名调用
2.static修饰方法===静态方法
static修饰方法----静态方法
跟类有关,跟对象无关。
【语法】 static 返回值类型 方法名()
【调用】类名.静态方法名
应用场合,Arrays
class Person{
static void staticfun(){
System.out.println("这是Person的静态方法");
}
}
public class Day5_1_ClassObject {
public static void main(String[] args) {
Person.staticfun();
Arrays.sort(a);
}
}
成员变量、方法、静态变量、静态的方法
在方法访问成员
[规则]: 非静态方法可以访问任何的变量、和方法(静态的和非静态)
静态的方法:只能访问静态方法和静态的变量(静态只能访问静态)
非静态方法中访问成员变量:可以
非静态方法中访问静态变量:可以
静态方法中访问成员变量:不可以
静态方法中访问静态变量:可以
封装/继承
this为当前创建的对象名(不是方法中的形参名)
super 调用父类的参数 方法 构造函数 不能和this同时存在
封装 get、set
public谁都可以调用
protected可以被自己类里的函数调用 可以被继承的类调用 不能被其他类调用
private只能被自己类里面的其他函数调用
default只能在当前包中其他类被使用
子类重写父类方法,调用时在子类中直接运行被重写的方法,不用父类的方法,否则调用子类的方法,用的是父类的方法
多态
前提:必须要有继承,子类要重写父类方法
多态:父类 对象=new 子类();
规则:编译看前面,父类类型,运行时看后面,子类类型。如果子类类型里面的方法父类没有,则不可调用
Person p1=new Man();
if(p1 instanceof Man){//(p1对象是否是Man类型)p1是否包含Man子类类型 //向下转型 返回true 表示是,否则不是该类型
Man man=(Man)p1;//p1强转成Man类型
man.smoking();再调用man中smoking方法
}
public class TestPerson {
public static void main(String[] args) {
/*
* Person p=new Person(); p.eat(); p.sleep();
*
* Man m=new Man(); m.eat(); m.sleep();
*
* Woman w=new Woman(); m.eat(); m.sleep();
*/
//多态
Person p1=new Man();
if(p1 instanceof Man){//(p1对象是否是Man类型)p1是否包含Man子类类型 //向下转型 返回true 表示是,否则不是该类型
Man man=(Man)p1;//p1强转成Man类型
man.smoking();//再调用man中smoking方法
}
}
}
//人类
class Person{
//属性
String name;
int age;
//方法
public void eat() {
System.out.println("吃方法");
}
public void sleep() {
System.out.println("睡方法");
}
}
//男人
class Man extends Person{
String hobby;
//重写
public void eat() {
System.out.println("男人要吃有营养的");
}
public void sleep() {
System.out.println("男人安静的在休息");
}
public void smoking() {
System.out.println("男人抽烟");
}
}
//女人
class Woman extends Person{
String beauty;
public void eat() {
System.out.println("女人要吃少的,会胖");
}
public void sleep() {
System.out.println("女人要早睡,不然会老");
}
public void shopping() {
System.out.println("女人购物");
}
}