Java学习(2):面向对象


一、面向对象编程

1. 设计对象并使用

  • 类:是对象共同特征的描述。
  • 对象: 是真是存在的具体实例。
  • 在java中必须先设计类,才能创建对象并使用

创建类

public class 类名{
    属性定义
        修饰符 数据类型 = 值;
    方法定义
        修饰符 返回值类型 方法名(参数列表){
        }
}


public class Car{
	//属性 成员变量
	String name;
	String price;
	//行为 方法
	public void start(){
	}
	public void run(){
	}
}

使用类 对象

类名 对象名 = new 类名();
Car c = new Car();

c.name; //访问属性
c.run(); //访问方法

类名大写,驼峰命名规则。 一个java文件可以定义多个类,但是只能一个类是public,而且必须和文件名一致。


public class Phone {
    public int Size = 14;
    public String Color = "Red";
    public String Call(String number){
        return "正在呼叫:"+number;
    }
}
 
public static void main(String[] args) {
    Phone p = new Phone();
    System.out.print(p.Call("13845054318"));
    p.Size = 100;
    System.out.print(p.Size);
}

2. 对象内存图

在这里插入图片描述
首先 main.class 加载到方法区。
在执行Car c 时 会在栈内存中 开辟一块空间。
= new Car();后 会在堆内存开辟一块空间。
设置属性时 c.name=“a”; 会在 堆内存开辟的空间中
堆中的方法存的是引用地址 引用的方法在方法区中。
Car c 中存的是 堆内存中的地址。

当堆内存中的对象,没有被任何变量引用指向时,就会被判定为内存中的垃圾。

3. 构造器

无参构造 任何类默认就自带了无参的构造函数,一旦定义了有参的构造函数,就需要自己写一个无参的构造函数。

public Car(){
}
new Car();

有参构造

public Car(String name,double price){
	this.name = name;
	this.price = price;
}
new Car("特斯拉",100.00);

4. 封装

面向对象的三大特性:封装,继承,多态。
隐藏具体实现的细节,对外提供可以访问的方式。便于调用者的使用。提高了复用性。

public class Phone {
    private int size;
    public void setSize(int s){
        size = s;
    }
    public int getSize(){
        return size;
    }
}

5. this关键字

this代表的是当前对象的地址。区分成员变量和局部变量同名的情况

public class Phone {
    private int size;
    public void setSize(int s){
        int size = 1;
        this.size = s;
    }
    public int getSize(){
        return this.size;
    }
}

6. javaBean

标准javaBean应该满足如下书写要求。

  1. 成员变量使用private修饰。
  2. 提供成员变量对应的get set方法
  3. 必须提供一个无参的构造函数。

7. 成员变量、局部变量区别

成员变量在类中,存在堆内存中,随着对象的创建而生,对象的消失而消失。
局部变量在方法中,存在栈内存中,随着方法的调用而存在,随着方法的结束而消失。

二、String

1. String类概述

String类定义的变量可以用于存储字符串,同时String提供了很多操作字符串的功能。

//String类是不可变字符串类型,一旦创建后不能被更改,但是内存地址是可以改变的。
String name = "aa";
name = "bb"; //其实是在堆内存中重新创建了一个字符串 将引用地址 重新复制给name变量。

比较

String str = "aa";
String str2 = "aa";
System.out.println(str == str2); //false 引用类型数据,==比较的是对象的地址
System.out.println(str.equals(str2)); //true equals 比较的是对象的内容

2. String类创建对象的2种方式


String str = new String("abcdefghijklmnopq123456"); //实际上创建了两个对象 堆中的字符串常量池一个  堆内存还有一个

String str = "sdfjklsdf"; //双引号创建的字符串对象,在字符串常量池中存储一个

Char[] c = {'a','b','c'};
String str = (c);
byte[] b = {97,98,99};
String str = (b);

String s1 = "abc";
String s2 = "a"+"b"+"c";
s1 == s2 ? //true. java编译优化机制,a+b+c 会直接转成abc 引用地址相同。

3. String类的常用方法

length()  返回字符串长度 字符个数
charAt(index) 获取某个索引处的字符
substring(startIndex,endIndex) 截取字符串 返回从开始到结束的字符串
startsWith(String prefix) 检测是否以此字符串开头
endsWith(String suffix) 检测是否以此字符串结尾
contains(String str) 判断字符串是否包含str字符串
indexOf(String str) 返回制定字符串在字符串中第一次出现的索引 没有返回-1
getBytes() 返回byte数组
toCharArray() 返回字节数组
equals(object obj) 字符串与指定对象比较
equalsIgnoreCase() 比较字符串不考虑大小写
toUpperCase() 转换大写
toLowerCase() 转换小写
replace() 替换字符串,使用的字符串
split() 参数分隔符 返回字符串数组

三、 ArrayList

1. ArrayList概述

ArrayList代表的是集合类,集合是一种容器,与数组相似,集合的大小是不固定的。
ArrayList集合的对象的创建

创建对象 ArrayList<数据类型>= new ArrayList<数据类型>();
ArrayList<String> arr = new ArrayList<String>();
数据类型不能是基本数据类型,必须是引用数据类型。

byte -> Byte
short -> Short
int -> Integer
long -> Long
float -> Float
double -> Double
char -> Character
boolean -> Boolean


ArrayList<Integer> nums = new ArrayList<Integer>();
nums.add(1); //插入到集合的末尾
nums.add(3);
nums.add(3);
nums.add(3);
nums.add(2,3333); //插入到指定索引

for(int i = 0;i<nums.size();i++){
    System.out.println(nums.get(i));
}


2. ArrayList的常用方法

add() 添加元素
get(index) 取出元素 索引取出
size() 返回长度 
set(index,element) 修改指定索引的元素
remove(index) 移除指定索引的元素
clear() 清空


四、 static关键字

  1. static是什么?
    static是静态的意思,可以用来修饰成员变量、成员方法。
    static修饰成员变量之后称为静态成员变量,修饰方法后称为静态方法。
    static修饰后的成员变量,可以被类的所有对象共享(访问、修改)。
public class Tai{
	//所有对象共享  静态成员变量 只在内存中有一份
	public static int onlineNumber = 160;
	public String name;
}

Tai.onlineNumber; //160


Tai tai = new Tai();
tai.onlineNumber ++; //161


  1. static修饰成员方法
//静态的方法可以直接 类名.方法名调用 不需要实例化

public class tai {
    public static void SayTai(){
        System.out.println("崩卡崩卡");
    }
}
tai.SayTai(); //静态不能调用非静态。
  1. static注意事项
    静态方法只能访问静态成员,不可以直接访问实例成员。
    实例方法可以访问静态的成员,也可以访问实例成员。
    静态方法中不可以使用this关键字。

代码块
在java类下,使用{}扩起来的代码称为代码块

  • 静态代码块
public static void main(String[] args) {
    System.out.println("main方法被执行了"); //后执行
    System.out.println(name);
}

public static String name;

//静态代码块 与类优先加载一次 自动触发执行
//可以用于初始化静态资源
static{
    name = "what";
    System.out.println("静态代码块被触发执行了"); //先执行
}
  • 构造代码块
    每次创建对象,调用构造器执行,在构造器执行前执行。
public class code2 {
    //实例代码块 每次构建对象都会被执行一次 在构造器之前执行
    {
        System.out.println("示例代码块执行"); //先执行
    }
    public code2(){
        System.out.println("构造器执行"); //后执行
    }
    public static void main(String[] args) {
        code2 c = new code2();
    }
}

五、 单例设计模式

开发中经常遇到的一些问题,一个问题有多种解决方案,其中最优的方案被总结出来了,称之为设计模式。
单例模式, 可以保证系统中,应用该模式的这个类永远只有一个实例。

  • 饿汉单例模式
    在用类获取对象的时候,对象已经提前为你创建好了。

首先把构造器私有
然后定义静态变量 new对象
最后定义静态方法 返回此对象

//饿汉单例模式 构造器私有化
public class SingleInstance {

    public static SingleInstance instance = new SingleInstance();

    //不对外 new对象
    private SingleInstance() {

    }

    public static SingleInstance getInstance(){
        return instance;
    }

}

//调用时
SingleInstance s1 = SingleInstance.getInstance();
SingleInstance s2 = SingleInstance.getInstance();
System.out.println(s1==s2); //true
System.out.println(s1.equals(s2)); //true        
  • 懒汉单例模式
    在真正需要使用该对象的时候才会去创建。
public class SingleInstance {

	//私有化
    private static SingleInstance instance; //默认是null

    //不对外 new对象
    private SingleInstance() {

    }

    public static SingleInstance getInstance(){
        if(instance == null){
            instance = new SingleInstance();
        }
        return instance;
    }

}

六、 面向对象:继承

1.继承概述

使用 extends 可以让一个类和另一个类建立父子关系。

public class Student extends People{

Student称为子类、People称为父类。
当子类继承父类后,就可以使用父类的公共属性和方法了

使用集成的好处,提高代码的复用性。

2. 继承设计规范

子类们相同的属性和方法可以放在父类中定义,自己独有的属性和方法定义在子类自己里面。
在堆内存中 一但Student对象初始化,则会创建两块内存空间,一块放父类,一块放子类。

3. 继承的特点

子类可以继承父类的属性和方法,但是子类不能继承父类的构造器。
Java是单继承模式,一个类只能继承一个直接父类。
Java不支持多继承,但是支持多层继承。
Java中所有的类都是Object类的子类。
父类静态成员属于共享成员,但不代表被子类继承。可以直接用。

4. 继承后成员变量、成员方法的访问特点

就近原则
现在子类局部范围找,然后子类成员范围找,最后父类成员范围找,还没找到就报错。
如果子类出现了重名的成员,则优先使用子类的。如果一定要使用父类的则使用super关键字。

5. 继承后 方法重写

在继承体系中,当父类和子类中的方法声明一模一样时,称为方法的重写。
当子类需要使用父类的功能,但父类的功能不满足自己需求时可以重写父类的方法。
@Override重写注解
放在重写的方法上,作为重写是否正确的效验注解。

public class People {

    public void say(){
        System.out.println("人说大家好");
    }
}


public class Student extends People{
    public Student(){
        super.say();
    }

    @Override
    public void say(){
        System.out.println("学生说好");
    }
}

Student s = new Student();
s.say();

//人说大家好
//学生说好

6. 继承后 子类构造器的特点

子类中所有的构造器默认都会先访问父类中的无参构造器,然后再执行自己。

public class People {
    public People() {
        System.out.println("父类无参构造器被执行了");
    }
    public void say(){
        System.out.println("人说大家好");
    }
}

public class Student extends People{
    public Student(){
        super.say();
    }

    @Override
    public void say(){
        System.out.println("学生说好");
    }
}


Student s = new Student();
//父类无参构造器被执行了
//人说大家好

子类构造器的第一行语句默认都是 super(); 不写也存在。

7. 继承后子构造器访问父有参构造器

子类调用父类有参构造器可以用来初始化父类的数据。

public class People {
    public String name;
    public People() {
        System.out.println("父类无参构造器被执行了");
    }
    public People(String name){
        this.name = name;
    }
    public void say(){
        System.out.println(name+"人说大家好");
    }
}

public class Student extends People{
    public String name;
    public Student(){
        super("父类名字");
        super.say();
    }


    @Override
    public void say(){
        System.out.println("学生说好");
    }
}

Student s = new Student();
//父类名字人说大家好

this代表本类本身,super代表父类存储空间的标识。

七、 包

java中的包,其实就是电脑中的文件夹,包中放的是类文件。
命名规则,全部小写,域名反写、com.xxx.web
package david.web; 包的声明 在第一行
导入包
import david.web.Outer; 具体到类名

1.同一个包下的类,互相可以直接访问。
2.不同包下的类,需要先导入包才可以访问。
3.如果一个类中需要用到不用类,而这两个类的名称是一样的,那么默认只能导入一个类,另一个类要带包名访问。

package com.test;

public class Stu {
}

package com.utils;

public class StringUtils {
    public void say(){
        System.out.println("say");
    }
}

导入

import com.utils.StringUtils;

八、 权限修饰符

用来控制一个成员能够被访问的范围。
可以修饰成员变量,方法,够再起,内部类。
在这里插入图片描述
1.仅能在本类中使用 private
2.本包中的类可以访问不加修饰符
3.本包中的类与其他包中的子类可以访问 protected
4.所有包中的所有类 public
一个文件中只能有一个public修饰的类,如果用public修饰则类名必须与文件名相同。

九、final

不可变
可以用来修饰类,类的成员,以及局部变量。
final修饰的类 不可以被继承,但是可以继承其他类。
final修饰的方法 不可以被子类重写。
final修饰的变量 称为常量,不会改变的值。
如果final修饰的变量是基本类型,那么变量存储的数据值不能发生改变。
如果final西施的变量是引用类型,那么变量存储的地址值是不能改变的,但是地址指向的对象内容是可以发生变化的。

final int age = 21;

final Student s =new Student();
s.name = "abc";
s.name = "cbd";
System.out.println(s.name); //cbd

十、 常量

常量就是使用了public static final 修饰的成员变量,必须有初始值,而且执行过程中不能改变。
命名规范:英文单词全部大写,多个单词用下划线连接起来。
常作为配置信息。

public static final String KEY = "8958530";

十一、 枚举

修饰符 enum 枚举名称{
}

public enum OrderStatus {
    PENDING,
    COMPUTE;
}

枚举类都是集成了枚举类型: java.lang.Enum
枚举都是最终类,不可以被继承。
构造器都是私有的,枚举对外不能创建对象。

javac OrderStatus.java 编译得到 .class文件
javap OrderStatus.class 反编译 得到如下

public final class com.OrderStatus extends java.lang.Enum<com.OrderStatus> {
  public static final com.OrderStatus PENDING;
  public static final com.OrderStatus COMPUTE;
  public static com.OrderStatus[] values();
  public static com.OrderStatus valueOf(java.lang.String);
  static {};
}

十二、 抽象类

在java中abstract是抽象的意思,可以修饰类,成员方法。

	public abstract 返回值类型 方法名(参数){}

抽象类不能被创建对象,因为抽象方法没有意义。
抽象类一定是个父类,如果没有子类重写他的方法,那么他将没有意义。

public abstract class Phone {
    //抽象函数 没有方法体
    public abstract void Call();
}


public class Iphone extends Phone{

    @Override
    public void Call() {
        System.out.println("abstract");
    }
}

final和abstract是互斥关系。
abstract定义的抽象类作为模板让子类继承,而final的类不能被继承。
抽象方法定义通用功能让子类重写,final定义的方法子类不能重写。

十三、 接口

接口是一种规范。
接口最主要的是用来解决多继承的弊端,将多继承这种机制在java中通过实现完成了。

public interface 接口名{
    抽象方法1;
    抽象方法2;
}

接口中的方法不能有方法体,属性必须为常量。方法可以不写public abstract

public interface Iphone{
    //常量
    public static final int Age = 18;
    //抽象方法
    public abstract void SayHi();
	//public abstract可以不写
	void haha();
}

实现一个接口使用关键字implements,并且实现接口的全部方法。

public class Phone implements Iphone{
	@Override
    public void SayHi(){
        System.out.print("接口"+ this.Age);
    }
}

多实现:
A implements B,C
在一个类中可以同时继承并且实现多个接口
A extends B implements C,D

JDK8之后新增方法
方法可以有方法体。

public interface AN {
    default void run(){
        System.out.println("wa o ");
    }
}

十四、 面向对象:多态

指对象可以有多种形态。
如:你在vs中按f1出现vs的帮助文档,在idea中按f1则会出现idea的使用帮助。

同类型对象,执行同一个行为,会变现出不同的特征。

父类类型或者接口类型 变量 = new 子类的对象();

Person p1 = new Student();
p1.run(); //方法 编译看左边Person的方法,运行看右边Student的方法
Person p2 = new Teacher();
p2.run();
System.out.println(p2.name); //变量 编译看左边,运行看左边

优势
在多态形式下,右边对象可以实现解耦合,便于维护和扩展。
比如 new Student(); 可以随意改为new Teacher();而不用改下面的逻辑。

在定义方法的时候,使用父类型作为参数,该方法就可以接收父类的一切子类对象。

public static void go(Person p){
        
}
//使用时
Person p = new Student();
go(p);

多态下不能使用子类独有功能,编译时就会报错。

多态的三个必要条件:继承、重写、父类引用指向子类对象

类型转换
自动类型转换 子到父。
强制类型转换 父到子。
子类 对象变量 = (子类)父类型的变量

Person s = new Student(); //自动
Student stu = (Student) s; //强制

强制转换时如果不符 则会报错。

Person p = new Teacher();
Student stu = (Student) p; //报错 无法转换

在转换前使用 instanceof 判断当前对象的真实地址,再进行强制转换。
对象变量名 instanceof 真实类型

 Person s =new Student();
 Person p = new Teacher();

 if(s instanceof Student){//true 
     Student stu = (Student) s; //执行
     stu.stufun(); //Student子类独有方法
 }
 if(p instanceof Student){ //false
     Student stu = (Student) p;//不会执行
     stu.stufun();
 }

强制转换后就可以使用子类的独有功能。

十五、 内部类

在一个类的内部定义一个类,成为内部类。
内部类可以访问外部类所有成员,哪怕是私有的。

// 外部类
public class Outer {
    private String haha = "哈哈大笑";
    //内部类
    public class Inner{
        public void HAHA(){
            System.out.println(haha);
        }
    }
}
 
//访问方式 外部类名.内部类名 变量名 = new 外部类名().new 内部类名();
Outer.Inner inner = new Outer().new Inner();
inner.HAHA();

局部内部类
方法中的内部类

public void out(){
     class Inner{
        public void inner(){
            System.out.println("内部类方法");
        }
    }
    Inner in = new Inner();
    in.inner();
}
调用out()方法时,自动调用内部类中的方法
class People {
    private int heartbeat = 150;

    public class Heart {
        private int heartbeat = 110;

        public void show() {
            int heartbeat = 78;
            System.out.println(heartbeat);// 78
            System.out.println(this.heartbeat);// 110
            System.out.println(People.this.heartbeat);// 150. 外部类.this.变量
        }
    }
}

匿名内部类
本质上是一个没有名字的局部内部类,定义在方法中、代码块中。
new 类|抽象类名|接口名(){
重写方法;
}

new AN(){ //实例化接口
    public void smoking(){
        System.out.println("smoking");
    }
}.smoking();



public abstract class Person {
    public abstract void run();
}

new Person(){ //实例化抽象类  抽象方法必须实现。
  @Override
    public void run() {
        //无需定义子类 快速实现方法
        System.out.println("Student");
    }
}.run();
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值