Java基础-面向对象

面向对象基础

类:数据类型(包含属性和行为)
对象:具体的实例

对象的创建与访问属性

public class cat{
    public static void main(String[] args) {
        cat cat1=new cat();//new cat()是创建的对象空间,cat1是引用的名字
        cat1.name="a";
        cat1.age=3;
        cat1.color="blue";
        
        System.out.println("cat1"+cat1.name+cat1.age+cat1.color);
    }
}
class cat{    //属性,field(字段),成员变量
    String name;
    int age;
    String color;
}

克隆对象

public class method{
    public static void main(String[] args) {
        Person p=new Person();
        p.name="fengwenjie";
        p.age=19;    
        Tools tool=new Tools();    //创建调用方法的对象
        Person p2=tool.copy(p);	//克隆p对象,具有相同属性
        System.out.println(p.name+" "+p.age);
        System.out.println(p2.name+" "+p2.age);
    }
}
class Person{
    String name;
    int age;
}
class Tools{
    public Person copy(Person p){    //克隆对象
        Person p2=new Person();
        p2.name=p.name;
        p2.age=p.age;
        return p2;
    }
}

对象内存布局

public static void main(String[] args) {
	Cat cat=new Cat();
	cat.name="小白";
	cat.color="白色"; 
}
class Cat{
	String name;
	String color;
}

在这里插入图片描述

方法

1.通过“."进行访问
2.方法使用:new一个对象,通过.调用方法
3.方法不能嵌套定义!
4.同一个类中的方法直接调用
5.跨类调用方法,通过new一个对象调用

6.方法调用机制:
执行方法时,开辟独立的占空间,执行完毕,返回调用者

7.访问修饰符:public private protected 默认

方法实例:返回数组的函数调用

public class method{
    public static void main(String[] args) {
        Tools tool=new Tools();
        int []res=tool.getSumAndSub(3,2);//数组接收
        System.out.println(res[0]+" "+res[1]);
    }
}
class Tools{
    public int[] getSumAndSub(int n1,int n2){
        int []resArr=new int [2];
        resArr[0]=n1+n2;
        resArr[1]=n1-n2;
        return resArr;
    }
}

传参机制

传参(parameter)机制:

1.基本数据类型:值拷贝,实参不改变
2.引用类型(数组,对象):地址拷贝

方法重载

方法名相同,形参个数不同

class Methods{	//返回不同类型的最值
	public int max(int n1,int n2){
		return n1>n2?n1:n2;
	}
	public double max(double n1,double n2){//两数最大值
		return n1>n2?n1:n2;
	}
	public double max(double n1,double n2,double n3){//三数最大值
		double max1=n1>n2?n1:n2;
		return max1>n3?max1:n3;
	}

}

可变参数

一个参数列表中只能包含一个可变参数

可变参数求和

public class overload{
	public static void main(String[] args) {
		Methods method=new Methods();
        //实参可以为数组
        int[]arr={1,2,3};
        System.out.println(method.sum(arr));
		System.out.println(method.sum(1,2,3,4));
	}
}
class Methods{	
	public int sum(int...nums){	//接受可变参数
		int res=0;
		for(int i=0;i<nums.length;i++)
			res+=nums[i];
		return res;
	}
}

可变参数和普通参数一起时,可变参数必须放在最后

public class overload{
	public static void main(String[] args) {
		Methods method=new Methods();
		System.out.println(method.showscore("milan",90.1,60));
		System.out.println(method.showscore("jack",90.1,60,80,88));
	}
}
class Methods{	
	public String showscore(String name,double...score){
		double totalscore=0;
		for(int i=0;i<score.length;i++)
			totalscore+=score[i];
		return name+"成绩总分为"+totalscore;
	}
}

作用域

局部变量:
定义在成员方法中的变量,只在方法体中使用

全局变量(属性):
作用域为整个类体

赋值:
局部变量必须赋值后使用
全局变量(属性)默认赋值
属性和局部变量可以重名,就近原则访问

生命周期:
执行完方法局部变量被销毁,属性任然可以使用

使用范围:
属性可以通过调用对象跨类访问,局部变量只能在本类中使用

修饰符:
全局变量可以加,局部不能加

构造方法/构造器

1.完成对新对象的初始化,不是创建对象
2.无返回值,方法名与类名相同
3.如果没定义,则系统会自动生成默认构造器,通过javap xx.class反编译
4.自己定义的构造器会覆盖默认构造器,不能再使用默认构造器了

public class constructor{
    public static void main(String[] args) {		 
        Person p1=new Person("smith",90);//第一个构造器
        Person p2=new Person("jack")//第二个构造器;
        Person p3=new Person();//无参构造器	
       System.out.println(p1.name+" "+p1.age);
       System.out.println(p2.name+" "+p2.age);
       System.out.println(p3.name+" "+p3.age);//name为默认null
	}
}
class Person{
	//直接初始化人的姓名和年龄
	String name;
	int age;
	//双参构造器
	public Person(String pname,int page ){
		name=pname;
		age=page;
	}
    //单参构造器
    public Person(String pname){
        name=pname;
     }
     //无参构造器
     public Person(){
        age=18;
     }
}

对象创建流程

class Person{
    int age;
    String name;
    Person(String n,int a)[
        name=n;
        age=a;
    }
Person p=new Person("小倩",20);

1.首先加载Person类
2.,在堆中创建对象
3.默认赋值,再显示初始化,遇到构造器再替换信息
4.将对象在堆中的地址返回给p

This关键字

哪个对象调用,this就代表哪个对象dog1和this的hashCode相同

Dog dog1=new Dog("jack",3);)
class Dog{
    String name;
    int age;
    public Dog(String name,int age){
        this.name=name;//当前对象属性
        this.age=age;
     }

比较两人的年龄和名字

Person p1=new Person('jack',19);
Person p2=new Person('tom',18);
System.out.println(p1.compareTo(p2));//p1相当于this
class Person{
    String name;
    int  age;
    public Person(String name,int age){
        this.name=name;
        this.age=age;
     }
     public boolean compareTo(Person p){
        return this.name.equals(p.name)&&this.age.equals(p,age);
     }

更改价格

public class homework{
	public static void main(String[] args) {
		 T t=new T();
		 Book book=new Book("笑傲江湖",300);
		 book.info();
		 book.upDataPrice();
		 book.info();
	}
}
class Book{
	String name;
	double price;
	public Book(String name,double price){//构造器
		this.name=name;
		this.price=price;
	} 
	public void upDataPrice(){//更新价格
		if(this.price>150){
			this.price=150;
		}
		else this.price=price;
	}
	public void info(){//打印
		System.out.println("书名"+this.name+"价格"+this.price);
	}
}

章末练习

返回数组最大值

public class homework{
	public static void main(String[] args) {
		double []arr={1,2,4,5,7};
		T t=new T();
		System.out.println(t.max(arr));
	}
}
class T{
	public double max(double []arr){
		double max=arr[0];
		for(int i=1;i<arr.length;i++){
			max=Math.max(max,arr[i]);
		}
		return max;
	}
}

返回字符串在数组中的下标

public class homework{
	public static void main(String[] args) {
		 T t=new T();
		 String[] strs={"jack","tom","mary"};
		 int index=t.find("tom",strs);
		 System.out.println(index);
	}
}
class T{
	public int find(String findstr,String[]strs){
		for(int i=0;i<strs.length;i++){
			if(findstr.equals(strs[i]))
				return i;
		}
		return -1;
	}

}

面向对象提高

访问修饰符

在这里插入图片描述

1 同一个类中都可以访问
2.相同包下除private都可以访问
3.不同包下只能访问public

修饰属性和方法
只有默认和public才能修饰类

封装

隐藏细节,验证数据安全
封装步骤:
1.将属性私有化(private属性)
2.创建set和get方法

继承

不同类的方法可以共用,代码复用

1.子类继承所有属性和方法,不能直接访问父类的私有属性和方法,要父类提供公共(public)方法

2.调用子类构造器时,会默认调用父类构造器

3.父类如果没有提供无参构造器,则必须通过子类
用super指定构造器完成对父类的初始化

4.super放在构造器第一行,super只能在构造器中使用

5.super(),this()只能用一个,放在第一行

继承内存布局

从顶级父类开始加载类,在堆中分别分配空间保存各个类的属性

在这里插入图片描述
访问顺序:
1.如果子类有就可以访问的属性/方法,则直接返回子类;否则向上查找父类的可以访问属性/方法。

2.如果找到但是不能访问,则报错

构造器调用顺序:this,super跳转

class A{
    A(){System.out.println("a");}
class B extends A{
    B(){this("abc")//调用下面的含参构造器
        System.out.println("b";}
    B(String name){
        //调用默认的父类构造器
        System.out.println("b name");)
//B b=new B() 输出 a   b name  b 

super

父类的引用,可以访问父类的非private属性/方法/构造器super.xx
调用方法的形式:

call();
this.call();
super.call();//直接从父类中查找

super与this的比较

在这里插入图片描述

方法重写

子类方法的名字,返回类型,参数相同,则子类覆盖父类方法

public class Animal{
    public void cry(){}
}
public class Dog extends Animal{
    public void cry(){}//重新父类方法
}

返回类型相同或者子类返回类型包含于父类

public Object m{}
public String m{}//String属于Object,重写m方法

子类不能缩小父类方法的访问权限
public>protected>默认>private

//父类
public String say(){return name+" "+age;}
//子类
public String say(){return super.say+id+score;}

方法重载与重写

在这里插入图片描述

多态

方法或对象具有多种形态,建立在封装和继承
1.方法重载,方法重写都有体现
2.对象多态
2.1一个对象的编译类型和运行类型可以不同
2.2编译类型在定义时确定,不能再改变,运行类型可以改变,通过getClass()查看
2.3编译类型看=左边,运行类型看=右边

Animal animal=new Dog();
animal.cry();//调用Dog类方法
Animal animal=new Cat();
animal.cry();//调用Cat类的方法

/*向上转型
   animal可以调用父类的所有成员,但是不能调用子类的特有成员,
运行效果取决于子类具体实现,从子类开始查找方法*/

//向下转型
Animal animal=new Cat();
Cat cat=(Cat)animal;//强转为Cat类的引用
cat.catchMouse();
Dog dog=(Dog)animal;//animal并不指向Dog,因此不能强转为dog

动态绑定机制:
1.调用对象方法时,方法会和运行类型绑定
2.调用对象属性时,没有动态绑定机制,哪里声明,哪里使用

多态数组
根据instanceof判断子类类型,调用特定方法

Person[]person=new Person[2];
person[0]=new Student("jack",20);
Person[1]=new Teacher("marry",30);.
for(int i=0;i<person.length;i++){ 
  //调用子类重写的方法say()
    System.out.println(person[i].say())
   //调用子类特有方法
   //instanceof判断运行类型是否为某类型或其子类型
    if(person[i] instanceof Student){
        Student student=(Student)person[i];//向下转型
        student.study();
        //(Student)person[i].study();
    }else if(person[i] instanceof Teacher){
        (Teacher)person[i].teach();
    }
}

多态数组排序

    //对象创建
            Person[]per=new Person[3];
            per[0]=new Person("jack",19,"cooking");
            per[1]=new Person("marry",20,"houseworking");
            per[2]=new Person("peter",22,"play");
    //按照对象的年龄排序
            for(int i=0;i<per.length;i++)
                for(int j=0;j<per.length-1-i;j++)
                    if(per[j].age>per[j+1].age){//比较属性
                       Person temp;//交换的是Person类的对象
                        temp=per[j];
                        per[j]=per[j+1];
                        per[j+1]=temp;
                    }       

Object类

equals方法

不可以判断基本数据类型,可以判断两个对象是否相等

   String string1 = new String("abc");
   String string2 = new String("abc");
   System.out.println(string1==string2);//false
   System.out.println(string1.equals(string2));//true

方法重写

public class jdk {
    public static void main(String[] args) {
        //比较两个对象的多个属性
        Person person1 = new Person("小明",18,'男');
        Person person2 = new Person("小明",18,'男');
        System.out.println(person1.equals(person2));
    }
}
class  Person {
    private String name;
    private int age;
    private char gender;
    //重写equals方法
    public boolean equals(Object obj) {
        if (this == obj) {//同一个对象返回true
            return true;
        }
        if (obj instanceof Person) {
            Person p = (Person) obj;//得到属性
            return this.name.equals(p.name) &&//equals(String)
                    this.age == (p.age) &&//基本类型用==
                    this.gender == (p.gender);
        } else {
            return false;
        }
    }
}

HashCode
不同对象的哈希值不同,主要根据地址

A a=new A();
A b=new A();
a.hashCode()!=b.hashCode();

toString
输出属性
返回值为类全名+哈希值的16进制值
直接输出对象会默认调用toString();

finalize
对象销毁前会自动调用finalize方法,回收没有引用的对象,释放资源

Car bm=new Car("宝马");
bm=null;//Car无引用被回收
System.gc();//运行垃圾回收器

面向对象进阶

静态

静态变量
1.static变量同类所有对象共享
2.静态变量在类加载时生成,不用创建对象实例

访问:
类名.静态变量名
不能通过此方法访问非静态变量

A.name;//类名.变量名访问
A a=new A();
a.name;//类实例访问
class A{public static String name="feng";}

静态方法/类方法
1.不创建实例也可以调用方法,则做成静态方法,直接通过类名调用

2.静态方法不能使用this/super,不能调用非静态方法

3.普通方法既可以方法静态也可以访问非静态方法

4.静态变量不会受构造器影响,只有在new创建实例时才会调用构造器

main方法

1.main方法由虚拟机调用

2.不用创建对象,因此是static

3.java 执行程序 参数1 参数2,传入[]args数组
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-E2mIFw0u-1674124788566)(en-resource://database/2203:1)]
4.main中只能直接访问static成员,否则必须创建实例才能访问非静态成员

代码块

在这里插入图片描述
提高构造器中代码复用性,代码块调用顺序优先于构造器
1.静态代码块随类加载而只会执行一次

2.类被加载的时机:
在这里插入图片描述

3.普通代码块每在对象创建(new)时就调用一次,调用静态变量才会调用静态代码块

4.创建一个对象时,一个类的调用顺序
1)先调用静态代码块和完成静态属性初始化
2)再调用普通代码块和完成普通属性的初始化
3)最后调用构造器

5.构造器先调用父类构造器,再调用本类代码块,最后执行自身内容

6.创建子类时的调用顺序
在这里插入图片描述

7.静态代码块只能调用静态成员,普通代码块能调用所有成员

单例设计模式

饿汉式–创建对象不一定使用

1)构造器私有化
2)内部创建static对象
3)提供public方法访问

girlfriend instance=grilfriend.getInstance();
class girlfriend{
    private String name;
    private static girlfriend gf=new girlfiend("marry");
    private girlfriend(String name){
        this.name=name;
     }
     public static girlfriend getInstance(){
        return gf;
   }

懒汉式—需要使用才创建
1)构造器私有化
2)定义static对象
3)提供公共访问方法,判断是否需要创建对象

class Cat{
    private String name;
    private static Cat cat;
    private Cat(String name){
        this.name=name;
     }
     public static Cat getInstance(){
        if(cat==null)//未创建时才创建
            cat=new Cat("herry");
        return cat;//返回上次创建的对象
   }

在这里插入图片描述

final

1)不希望被继承

final class Person{}

2)阻止子类重写父类方法
可以继承,不能重写

public final void hi(){}

3)属性/变量不能修改
常量必须赋值:

private final double PI=3.14;//定义
pulic Circlle(double radius){//构造器
    this.radius=radius;
    PI=3.14;
}
    {PI=3.14}//代码块

静态属性不能在构造器中赋值,而是要在静态代码块中赋值

public final double TAX_RATE=0.09;
final double NUM=0.01;

4)final类中不用声明final方法

5)final+static阻止类加载

//主方法调用num时不会加载代码块
public final static int num=1000;
static{};//不会被调用

抽象类

父类方法不确定,设计为抽象方法,没有实现的方法,通过子类实现

abstract class Animal{//声明抽象类
     public abstract void eat();//抽象方法
}

1)抽象类不能实例化,不能new

2)抽象类可以没有抽象方法,含抽象方法的必须是抽象类

3)abstract只能修饰类和方法

4)继承抽象类必须实现所有抽象方法,除非自己也声明为抽象类

5)抽象方法不能使用private,final,static,因为与继承相违背
模板:

abstract class Template{//模板类
    public  abstract void job();//抽象方法

    public void Calculate(){
        long start=System.currentTimeMillis();
        job();
        long end=System.currentTimeMillis();
        System.out.println(end-start);
    }
}
class A extends Template{
    public void job(){//必须重写job()
        long num=0;
        for(long i=0;i<100000;i++){
             num+=i;
        }
    }
}
public class Main{
    public static void main(String[] args) {
        A a=new A();
        a.Calculate();//调用  
    }
}

抽象方法例子

abstract class Animal{
    public abstract void shout();
}
class Dog extends Animal{
    public void shout(){
        System.out.println("狗叫");
    }
}
class Cat extends Animal{
    public void shout(){
        System.out.println("猫叫");
    }
}
public class hhh{
    public static void main(String[] args) {
    Animal dog=new Dog();
    Animal cat=new Cat();
    dog.shout();
    cat.shout();
    }
}

接口

接口就是一些没有实现的方法,封装到一起,到需要使用某个类时,在根据需要实现具体的方法

interface 接口名{//public或者默认
    //属性
    //方法(抽象方法/default/static)
    }
 class A implements 接口{
    //必须实现接口所有方法
    //alt+enter
    }
class C implements A,B{}//实现多个接口
interface IB{
   int n1=10;
 //实际是public static final int n1=10
 }
 
 //接口继承
 interface A{}
 interface B extends A{}
 
 //可以通过A.a B.a访问属性
 interface A{int a=10}
 class B implements A{}

接口是对单继承机制的补充
子类扩展功能可以通过接口实现

class LittleMonkey extends Monkey implements Fish,Bird{}

接口数组

public static void main(String[] args) {
	Usb[]usbs=new Usb[2];
	usbs[0]=new phone();
	usbs[1]=new camera();
	for(int i=0;i<usbs.length;i++){
		usbs[i].work();
		//类型判断,实现特定方法
		if(usbs[i] instanceof phone){
			((phone)usbs[i]).call();
		}	
	}
}
interface Usb{
	work();
}
class phone implements Usb{
	public void work(){}
	public void call();//特有方法
}
class camera implements Usb{
	public void work(){}
}

在这里插入图片描述

interface Vehicles{
    public void work();
}
//实现接口不要忘了implements!!
class Horse implements Vehicles{
    public void work(){
        System.out.println("一般使用马");
    }
}
class Boat implements Vehicles{
    public void work(){
        System.out.println("过河用船");
    }
}
//get()方法
class Factory{
    private static Horse horse=new Horse();//饿汉式
    public static Horse getHorse(){
        return horse;//每次不用new一个Horse();
    }
    public static Boat getBoat(){
       return new Boat();
    }
}
class Person{
    private String name;
    private  Vehicles vehicles;
    public Person(String name,Vehicles vehicles){
        this.name=name;
        this.vehicles=vehicles;
    }
    //封装
    public void PassRiver(){
        //vehicles不是船时就用船
        if(!(vehicles instanceof Boat)){
           vehicles=Factory.getBoat(); 
        }
        vehicles.work();
    }
    public void Common(){
        //不是马就用马
        if(!(vehicles instanceof Horse)){
            vehicles=Factory.getHorse();
        }
        vehicles.work();
    }
}
public class Main{
    public static void main(String[] args) {
        Person person=new Person("唐僧",new Horse());
        person.PassRiver();
        person.Common();
    }
}

内部类

类成员:属性,方法,构造器,代码块,内部类

局部内部类

1)不能添加修饰符,可以用final

2)作用域在方法体中

3)可以访问外部类成员,outer.this.xx;

class outer{
    private int n1=10;
    public void f(){
        class inner{//方法体中
        private int n1=20;
        //调用外部的n1  outer.this.n1
        public void f2();}
        }
     inner in=new inner();//创建内部类对象访问方法
     in.f2();
   }

匿名内部类

//通过对象调用
Person p=new Person{
    void do{};
    };
    p.do();
//直接调用
new Person(){
     void do();//重写Person()的do()方法
     }.do();

传递接口的匿名内部类

interface Bell{
    void ring();
}
class CellPhone{
    public void alarm(Bell bell){
        bell.ring();
    }
}
public class hhh{
    public static void main(String[] args) {
        CellPhone phone=new CellPhone();
        phone.alarm(new Bell(){
            public void ring(){//public权限
                System.out.println("起床了");
            }     
        });
    }
}

应用:传入实现接口的方法参数

public class hhh{
    public static void main(String[] args) {
        Phone phone=new Phone();
        //传入实现接口的方法的参数
        phone.test(new Calcu(){
            public double work(double n1,double n2){
                return n1+n2;
            }
        },1,2);
    }
}
interface Calcu{
    public double work(double n1,double n2);
}
class Phone{
    //传入接口参数
    public void test(Calcu calcu,double n1,double n2){
        double res=calcu.work(n1,n2);
        System.out.println(res);
    }
}

成员内部类

不在外部类的方法中,直接定义在外部类成员位置上

class outer{
    class inner{ //成员内部类
        void say();
    }
    public void test(){//作为调用内部类的桥梁
        inner in=new inner();
        in.say();
    }
}
class Main{
    outer ot=new outer();
    ot.test();//调用成员内部类方法
    }

在这里插入图片描述

public class Main{
    public static void main(String[] args) {
        Car car=new Car(60);
        //通过get方法调用
        car.getAir().flow();
    }
}
class Car{
    private double temper;
    public Car(double temper){
        this.temper=temper;
    }
    class Air{
        public void flow(){
            if(temper>40){
                System.out.println("吹冷气");
            }else if(temper<0){
                System.out.println("吹暖气");
            }else{
                System.out.println("温度正常");
            }
        }
    }
    //返回得到内部类对象的方法
    public Air getAir(){
        return new Air();
    }
}

静态内部类

class outer{
    private static int n1=10;
    private static void work();
    static class inner{ //静态内部类
       static int n1=20;
        public void say(){
            System.out.println(n1);//就近原则访问静态属性
            System.outprintln(outer.n1);//outer.xx,访问外部属性
            work();//调用静态方法
        }
    }
}
class Main{
    public static void main(String[] args) {
        outer.inner in=new outer.inner(); //静态内部类对象
        in.say();//其他类访问内部类
    } 
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值