面向对象程序设计

面向对象(将程序模块化)

  • 面向过程->开发效率低,维护成本高;面向对象->忽略过程中的细节,事物模块化
  • 类和对象
每个对象都有特定的特征:属性(静态特征)、方法(动态特征)
类是产生对象的模板,是对象的抽象化描述,对象是类的具体实例
Java程序是以类为单元,程序运行时的主体是通过类创建的具体对象

定义类

public class 类名{
    //定义属性,属性名(驼峰式)
    public 数据类型 属性名;
        //定义方法
    public 返回值类型 方法名(数据类型 参数名){
        //方法体
    }
}


构造方法(构造函数;构造器)

普通方法:描述动作
构造方法:创建对象
  • 方法名与类名一致
  • 不需要定义返回值类型
构造函数可分为有参构造和无参构造(有无参数)
任何一个类都默认自带一个无参构造函数,如果手动在类中定义一个有参构造,则会覆盖默认的无参构造
class Student{
    public String name;
    public int ID;
public Student(String N,int i){//构造方法(有参构造)
    name=N;
    ID=i
}
public void ChangeName(String NewName){//普通方法
    name=NewName;
}
    
}


调用方法

类 . 方法(参数列表);  //例:teacher.lesson(work);

方法重载

在一个类中允许同名的方法(普通/构造方法)存在(参数声明不同——>数据类型不同;形参顺序不同;参数的数据类型相同但参数个数不同)(与参数名称和返回值类型无关)
//方便调用时可以灵活地创建出不同需要的对象
//重载的多个构造方法实际上就是相当于提供了多个初始化new对象的模板


方法的可变个数的参数

前提:可能要给方法传递不同个数的参数
将方法中的参数定义为String类型的数组,调用方法时传入字符串数组即可
没有参数可以不填
放在所有参数之后
public void PrintInfo(String...args){  // Java特有的方式,代表0到多个参数
    for(int i=0;i<args.length>
public class Test{
    public static void main(String[] args){
        Person p=new Person();
        String[] a=new String[]{"1","woshidage","2333"};
        p.PrintInfo(args);
    }
}


方法的参数传递

方法必须有其所在类或对象调用才有意义,含有(形参:方法声明时的参数;实参:方法调用时实际传给形参的参数值)
Java例方法的参数传递只有值传递
如果方法的形参是基本数据类型,那么实参(实际的数据)向形参传递参数时,就是直接传递值,把实参的值复制给形参
如果方法的形参时对象,那么实参(实际的对象),向形参传递参数的时,也是把值传给形参,这个值是实参在栈内存中的值,也就是引用对象在堆内存中的地址
基本数据类型都是保存在栈内存中,引用对象在栈内存中保存的是引用对象的地址,那么方法的传递参数是传递值(变量在栈内存中的值)
</args.length>


成员变量和局部变量

变量的作用域:在程序中可以通过变量名来访问该变量的范围,变量的作用域由变量被声明时所在的位置决定的。
Java中根据不同的作用域可以将变量分为成员变量和局部变量
局部变量:如果一个变量在方法中声明,则该变量时局部变量(作用域小,高优先级)
成员变量:如果一个变量在方法外,类中声明,则该变量是成员变量(作用域大,优先级低于参数列表和局部变量)
二者区别:作用域不同(成员变量的作用域在整个类中,类中的每个方法都可以访问该变量;局部变量的作用域只在定义该变量的方法中,出了方法体就无法访问)
初始值不同(局部变量不会赋初值,成员变量会赋初值,由数据类型决定)

包(package)

整理文件(作用):文件太乱不好管理、文件同名
package 顶层包名 . 子包名;(可以有多级)
包用小写单词,类名首字母大写

引用(import)

位于package下,使用定义在不同包中的Java类
使用方法:import    包 . 包 . 类(或*,代表包中所有类);        //包 . 包 . 类 . 变量 = new 包 . 包 . 类();

封装
指将类的属性隐藏在内部,外部不能直接访问和修改(防止出现的变量不合常理)
为了保护变量信息,通过修改成员变量的可见性,从公有改为私有(public->private)
封装的核心思想就是把属性都隐藏在内部,对外提供方法来访问和操作,我们可以在这些方法中添加逻辑处理来实现过滤,以屏蔽错误数据的赋值
封装的步骤:
  • 修改属性(成员变量)的访问权限为私有,使外部不能直接访问
  • 提供外部可以直接调用的方法(方法为public类型,一般有setXxx和getXxx)
  • 在方法中加入对于属性的逻辑控制,避免出现逻辑错误
访问权限:该属性可以被直接访问的范围,是在属性定义时设定的
(public、private、不写、protected)作用于范围不同
import java.util.Scanner;

public class Person{
    private int age;
    
    public void printAge(){
        System.out.println("年龄是"+age);
    }
    
    public void setAge(){  System.out.print("请输入年龄:");
        Scanner sc=new Scanner(System.in);
        int a;  while(true){  a=sc.nextInt();
            if(a <= 150 && a >= 0){
            age = a;
                break;
            }
            else{  System.out.print("输入的年龄不符合规则,请重新输入:");
            }
        }
    }
}

this关键字

当形参与成员变量重名时,如果在方法内部需要使用成员变量,必须添加this来表明该变量时类成员
·   在任意方法内,如果使用当前类的成员变量或成员方法可以在其前面添加this,增强程序的阅读性
this用来指代当前类的实例化对象,通过this可以调用当前类的属性和方法(例:在有参构造中,通过this将外部传入的值赋给当前类的实例化对象)
this还可以在类中调用方法,用this调用构造/普通方法的语法不同(前:this(参数列表)->不能在普通方法中使用this调用构造函数;后:this.方法名(参数列表)->在构造函数和普通方法中都可调用)
        this();//调用无参构造方法,实现同一个类中构造方法相互调用的特殊格式(禁止套娃:无法同时相互调用;调用自身)


JavaBean

JavaBean是指符合如下标准的Java类:
类是公有的(public)
有一个无参的公共的构造方法
有属性,且属性为private,有对应的set、get方法
快速定义set、get方法:
前提:写好private类型的属性
步骤:鼠标右键->Source->Generate Getters and Setters...->g

Static(全局)

static表示静态或者全局,可以用来修饰成员变量和成员方法以及代码块(可以不用对象而访问方法)
使用static修饰的成员变量和成员方法独立于该类的任何一个实例化对象,访问时不依赖于该类的对象,而是直接通过类访问(被该类的所有实例对象所共用)
static可以修饰代码块(静态代码块),特点:只执行一次(because类也只执行一次),当类被加载到内存时自动执行,不需要开发者手动调用
static{
    System.out.print(1);
}


继承

描述类之间的关系:一个类继承(拥有)另一个类的属性和方法(父类->子类)(基类——派生类)
把共性的东西抽象为父类,有需求的子类在继承父类的基础上写自己特有的代码(子类是对父类的"扩展")
基本语法:
public class 类名 extends 父类名{    //子类 is a 父类
    
}
子类拥有父类和自己特有的属性和方法(不能继承父类构造方法
Java中的继承时单继承,一个子类只能有一个父类----所有类都有一个共同父类Object
作用:
提高代码复用性
让类与类之间产生了关系,提供了多态的前提
继承存在逻辑关系,不要仅为了获取其他类中某个功能而去继承(例:人和狗具有一些相同的相同的属性,如名字、年龄、性别,但是狗不能继承人的类)


子类访问父类
创建子类对象时,会默认先创建一个父类对象,无论是通过有参构造或是无参构造来创建子类对象,都是默认通过无参构造来创建父类对象的
可以通过super关键字让子类创建对象时调用父类的有参构造
public Student(){
    super(参数);
    System.out.println("通过无参构造创建了Student对象");
}

继承的传递性

多层继承:一个子类可以当成父类被继承(Object->父类->子类1->子类2.......)

super关键字

子类可以访问和调用父类的构造方法、普通方法、成员变量,都是通过super关键字来完成
通过super,子类可以调用所有父类层级
语法:
构造方法:super();
普通方法:super.方法名(参数列表);
成员变量:super.成员变量名;
子类中所有的构造方法不能访问父类无参构造
在父类只有有参构造可以使用时,子类需调用父类的有参构造,并且调用父类构造方法要写在第一行

在子类的构造方法中,可以通过super访问父类的构造方法和普通方法
在子类的普通方法中,只能通过super访问父类的普通方法
子类不能直接访问父类中私有的(private)的成员变量和方法

在子类中使用构造方法

子类不能继承父类的构造方法。子类在创建新对象时,依次向上寻找其基类,找到最初的基类
执行最初的基类的构造方法,再依次向下执行派生类的构造方法,直至执行完最终的扩充类的构造方法为止
构造方法不能被继承,它们只属于定义它们的类

创建一个子类对象时,首先调用父类的构造方法,接着才执行子类构造方法

访问权限修饰符

private:类内部
default:类内部,同一个包
protected:类内部,同一个包,子类
public:任何地方
对于class的权限修饰只能用public和default(同一个Java文件中可以写多个class,但只有一个class能被public修饰)

如果子类和父类在同一个包下,子类可以使用父类非private修饰的成员
如果子类和父类不在同一个包下,子类只能使用父类中protected和public修饰的成员

方法重写(override)

子类在父类方法的基础上,对父方重新定义并覆盖的操作(同名覆盖)
规则:1.构造方法不能被重写
2.父子类的方法名、返回类型、参数列表相同
3.子类方法的返回值与父类方法的返回值类型相同或是其子类
4.子类方法的访问权限不能低于父类

方法重写-方法重载

位置:(在子类中对父类进行重写)(在同一个类中)
方法名:(均相同)
参数列表:(相同)(不同)
返回值:(相同或是子类)(没有要求)
访问权限:(不能小于父类)(没有要求)


多态(Polymorphism)

一个事物具有多种表现形态,在Java程序中,定义一个方法,在具体的生成环境中根据不同的需求呈现不同的业务逻辑
Java引用变量有两个类型:编译时类型(由声明变量时使用的类型决定)、运行时类型(由实际赋给变量的对象决定)
如果编译时类型和运行时类型不一致,就出现多态(对象的多态)

对象的多态

在Java中,子类对象代替父类对象使用,一个引用类型变量可以指向多种不同类型对象
Person P=new Student();  //  父类的引用对象指向子类的实例

Person P=new Person();
P=new Student();  //P指向Student类型的对象
·  子类可以看作是特殊的父类,所以父类类型的引用可以指向子类的对象:向上转型(upcasting)
一个引用类型变量如果声明为父类的类型,但实际引用子类对象,那么该变量就不能再访问子类中添加的属性和方法

虚拟方法调用

Person e=new Student();
e.getInfo();  //调用Student类的getInfo方法
//  编译时e为Person类型,而方法的调用是在运行时确定,所以调用的是Student类的getInfo()方法(存在于方法重写之上)

多态的具体使用
1.定义方法时形参类型为父类,实际调用方法时传入子类类型的参数
2.定义方法时返回值类型为父类,实际调用方法时返回子类对象
基本原理:父类引用可以指向子类对象

instanceof  操作符

x  instanceof  A :检验对象x是否为类A的对象,返回值为boolean型
要求:x所属的类与类A为父子类关系
如果x属于类A的子类B,x  instanceof  A也为true
Person e=new Student();
e instanceof Student;  //  true

Object类

Object类是所有Java类的根父类(基类)
如果在类的声明中未使用extends关键字指明父类,则默认父类为Object类
多层继承,处于最高层的父类一定是Object类
public class Test{
    public void test(Object obj){
        //不确定传进来的类,可以确定传递实参一定是个类
    }
    public static void main(String[] args){
        Test t=new Test();
        Person p=new Person();
        Student s=new Student();
        t.test(p);
        t.test(s);
    }
}

对象类型转换

基本数据类型转换

int i=20;
double d=i; // 自动类型转换

long l=10l;
int i=(int)l; // 强制类型转换

Java对象的强制类型转换(造型)

· 从子类到父类的类型转换可以自动进行
· 从父类到子类通过造型实现
· 无继承关系的引用类型间的转换非法
public void method(Person e){
    if(e instanceof Student){
        Student s=(Student) e;
        s.getschool();
    }else{
        e.test();
    }
}


==操作符和equals方法

基本类型比较值
int i=3;
System.out.println(i == 4); // false
引用类型比较:只有指向同一个对象时,== 才能返回 true (两边的数据类型必须兼容)
Person p1 = new Person();
Person p2 = new Person();
System.out.println( p1 == p2 ); // false
Person p1 = new Person();
Person p2 = p1;
System.out.println( p1 == p2 ); // true

equals方法

所有类都继承了Object,获得 equals () 方法,可以重写
例:obj1 . equals( obj2 ) ; // 只能比较引用类型,比较是否指向同一个对象
String s1 = new String("abc");
String s2 = new String("abc");
System.out.println( s1 == s2 ); // false
System.out.println( s1.equals(s2) ); // true
对于对象来说,特殊的类,如String、File、Date,使用 == 比较的是对象的地址;equals  ( ) 比较的是内容
除了特殊的类之外的其他普通的类的对象, == 和equals ( ) 比较的都是对象内存地址(可重写equals方法)

String类型的创建

 // 字面量创建String对象
String s1 = "abc"; // 常量池添加"abc"对象,返回引用地址给s1
String s2 = "abc"; // 通过equals方法判断常量池已有,返回相同引用
System.out.println( s1 == s2 ); // true


 // new创建String对象,一定会创建新对象,地址不重复

String s3 = "x" + "y"; // 在常量池中添加"xy"对象
String s4 = new String("1") + new String("2"); // 在常量池中添加"1"和"2"两个对象,在堆中创建为"12"的对象,再引用地址

包装类

针对八种基本定义相应的引用类型 - 包装类(封装类)
boolean - Boolean
byte - Byte
short - Short
int - Integer
long - Long
char - Character
float - Float
double - Double
作用:
装箱:把基本数据类型包装成包装类
int i = 500 ;
Integer t = new Integer( i );
Float f = new Float("4.56");
Long l = new Long("asdf"); // 报错

拆箱:获得包装类对象中包装的基本类型变量
// 调用包装类的.xxxValue()方法;
Integer i = new Integer(111); // Integer i = 111  自动装箱然后赋值
System.out.println(i); // 111(自动拆箱然后输出)
int i0 = i.intValue(); // 拆箱

boolean b = new Boolean( "false" ).booleanValue(); // boolean b = new Boolean( "false" );  自动拆箱
Boolean B = true; // 自动装箱
System.out.println( b ); // false
// 主要应用:

Integer i = Integer.parseInt("123");
Float f = Float.parseFloat("0.40");
Boolean b = Boolean.parseBoolean("false"); // 字符串转换成基本数据类型  String istr = String.valueOf(i); // 基本数据类型转换成字符串

toString

父类Object的toString作用:输出当前对象的内存地址
如果想要输出类的其他信息,需要重写toString方法
public String toString(){
    String str = this.getName() + " " + this.getAge();
    return str;
} // toString方法重写,用于打印对象

public void toString(){
    System.out.println( this.getName() + " " + this.getAge );
} // 另一种形式

static关键字

无论产生多少对象,static修饰的数据在内存空间中只有一份,可以被所有对象共享(不因对象不同而改变)
实例变量:只有实例化之后才能使用,属于实例化对象的一部分
类变量(静态变量):不用实例化,直接通过类名使用,属于类的一部分,被所以有类的实例化对象共享(例如与创建对象有关的计数方法)
常用:类方法作工具类(例如判断字符串是否为空的方法,这一类方法可以抽取到同一个类中形成工具类),不需要创建对象就可以调用,简化方法调用过程
特点:
随着类的加载而加载
优先于对象存在
修饰的成员被所有对象共享
访问权限允许时,可以不创建对象而直接被类调用
修饰的方法内部不能有this
public class Chinese{
    public String name;
    private int age;
    public String country; // static String country;  country为类变量(静态变量)

        public static void Test(){
            System.out.println("这是一个静态方法");
        }
}

public class Main{
    public static void main(String[] args){
     // Chinese.country = "China";
        Chinese c1 = new Chinese();
        c1.country = "China"; // 可以注释掉
        Chinese c2 = new Chinese();
        c2.country = "China"; // 可以注释掉
     // System.out.println(Chinese.country);  直接通过类名设置和访问
    }
}

单例(Singleton)设计模式

单例:只有一个实例化对象(在整个软件系统运行过程中,这个类只被实例化一次,只调用这个实例)
设计模式:在大量的事件中总结和理论化之后优选的代码结构、编程风格、解决问题的思考方式
总结出的解决问题的套路
应用:实例化对象的创建需要消耗大量的时间和资源
public class Single{
    public Single(){
        // 假设构造中执行复杂代码(耗时很长)
    } // 适合使用单例模式
}

实现方式—饿汉式

定义:在类中初始化定义一个静态实例化对象,之后实例化都是这个对象
public class Single{
    private Single(){
        
    } // 构造方法私有化,调用类时无法使用new创建对象

private static Single s = new Single(); // 私有的Single类型的类变量,只有一个

public static Single getInstance(){
        return s;
    } // 使用已定义的类变量
}

实现方式—懒汉式

定义:最开始对象是null,直到第一个人调用,才new一个对象,之后调用的都是这个对象
public class Single{
    private Single(){
        // 私有化构造
    }
    
    private static Single s = null; // 将s初始化为空
    
    public static Single getInstance(){
        if( s == null ){
            s = new Single(); // 第一个实例化时定义对象
        }
        return s;
    }
}

理解main方法

public static void main(String[] args){
// 公有的、类方法、无返回值、方法名、传进字符串数组
}
由于Java虚拟机需要调用类的main()方法 -> 访问权限为public,不必创建对象 -> static,接收String类型的数组参数,保存执行命令时运行的参数
public class TestMain{
    public static void main(String[] args){
        for(int i=0,i<args.length>
	

模板方法设计模式

抽象类是子类的通用模板
把不确定的功能内部实现暴露出去让子类实现

final关键字

final修饰的类无法被继承 // public final class Test { }
final修饰的方法不能被子类重写 // public void Test () { }
final修饰的变量称为常量,只能被赋值一次 // final static int I = 0; 定义时完成赋值,final和static共同修饰为全局常量
// 常量定义名称使用大写,多个单词用 _ 连接 </args.length>

抽象类

没有具体实例(无法实例化)的父类,保证子类共享特征,抽象类是类的模板,属性和方法抽象化处理
abstract可以修饰类、方法,使之成为抽象类、方法 // 例:public abstract void Test ( ) ;
含有抽象方法的类一定是抽象类;抽象方法不一定含有抽象类;
抽象类的子类需要重写父类的抽象方法,并提供方法体,除非子类也是抽象类

接口

接口(interface)是抽象方法和常量值的定义的集合,实现多重继承的效果
接口是一种特殊的抽象类,只包含常量和方法的定义,没有变量和方法的实现,没有构造方法
实现接口类:
interface Interface1 { } // 方法默认为 public abstract  ;属性默认为 public static final
public class Test implements Interface1 { }

一个类可以实现多个接口,接口可以继承其他接口
实现接口的类需要实现接口的所有方法,否则就要定义成抽象类

一个类既继承父类又实现接口,先extends再implements

泛型

泛型类

class A{ // 泛型T可以任意取名,一般使用T(type)
    private T key;
    
    public void setKey(T key){
        this.key = key;
    }
    public T getKey(){
        return this.key;
    }
}
Aa = new A(); // 在new对象中指定泛型类型String
a.setKey("xxx"); // 对象使用中key的类型为String
String a1 = a.getKey(); // t.getKey返回值类型也是String
Aa2 = new A();
a2.setKey(1);
Integer i = a2.getKey();  //  <>中如果没写就是Object类型

泛型接口

public interface IB{
    public T test(T key);
}
 // 未传入实际泛型
public class B1implements IB{
    public T test(T t){
        return t;  //  B1b1 = new B1();
    }
}

public class B2 implements IB{
    public String test(String t){
        return t;    //    B2  b2  =  new B2();
    }
}

泛型方法

public class C{
    publicvoid main(T s){
        T t = s;
    }
    
    public String void test1(String s){
        return s;
    }
}



全部评论

相关推荐

1 收藏 评论
分享
牛客网
牛客企业服务