一、什么是面向对象、类
1.什么是对象?
对象是类的实例,具有具体属性和行为,一切客观存在的事物都是对象。
2.什么是类?
类是对大量对象共性的抽象,类是客观事物在人脑中的主观反映,类是对象的模板,定义对象的属性和方法。
例如:动物类有名字和肤色特征,会叫会吃喝,等等。
从而得出,类的组成是属性和行为。
3.类的分类?
(1)普通类(class)
普通类是 Java 中最常见的类类型。它可以有属性(成员变量)和方法,并且可以创建该类的实例(对象)
public class Student {
//学生类
}
作用:普通类用于表示现实世界的实体,并封装数据和行为(通过属性和方法)
-
可以实例化(即创建对象)
-
可以有构造器、成员变量、方法
-
可以继承其他类并实现接口
(2)抽象类(abstract class)
抽象类是一种不能被实例化的类,它通常用于表示通用的概念,具体的实现交给其子类完成。抽象类中可以有抽象方法(没有方法体),也可以有已实现的方法。
//抽象类
abstract class Animal{
// 抽象方法-没有实现
public abstract void makeSound();
// 普通方法
public void eat() {
System.out.println("动物在吃东西");
}
}
作用:用于表示通用的行为和属性,具体的实现由子类来完成
-
不能实例化,只能通过继承来使用
-
可以包含抽象方法(没有实现)和普通方法(有实现)
-
子类必须实现抽象类的所有抽象方法,否则子类也必须是抽象的
(3)接口(Interface)
接口是一个纯抽象的类,它只定义方法的签名(方法名、参数和返回值),不包含方法的具体实现。接口用于定义类必须实现的功能。
interface Phone {
void Call(); // 抽象方法
}
作用:接口定义类应该具备的行为,但不提供具体的实现,主要用于规范类的行为
-
不能包含实例字段,只能有常量和抽象方法(Java 8 后可以有默认方法和静态方法)
-
一个类可以实现多个接口(多重继承)
-
所有方法都是 public 且 abstract,默认情况下接口中的方法就是抽象的
(4)内部类(Inner Class)
内部类是在另一个类中定义的类。内部类可以访问外部类的成员变量和方法,它主要用于逻辑上和外部类关联的类。
public class Outputs {
private String message = "输出一个好消息";
// 内部类
class Inputs {
public void displayMessage() {
System.out.println(message); // 可以访问外部类的成员变量
}
}
public static void main(String[] args) {
// 创建外部类对象
Outputs outer = new Outputs();
// 创建内部类对象
Outputs.Inputs inner = outer.new Inputs();
inner.displayMessage(); // 输出: 输出一个好消息
}
}
作用:内部类用于封装与外部类紧密相关的功能,提供更好的封装性
-
内部类可以访问外部类的所有成员变量和方法
-
内部类对象的创建依赖于外部类对象
-
内部类可以隐藏在外部类内部,增加了封装性和可读性
(5)静态内部类(Static Nested Class)
静态内部类是内部类的一种,但它不依赖于外部类的实例。静态内部类无法访问外部类的非静态成员。
public class OuterClass {
private static String staticMessage = "来自静态嵌套类的Hello";
// 静态内部类
static class StaticNestedClass {
public void displayMessage() {
System.out.println(staticMessage); // 只能访问外部类的静态变量
}
}
}
作用:用于逻辑上与外部类关联,但不依赖外部类实例的类
-
静态内部类不能访问外部类的非静态成员变量
-
静态内部类可以直接通过外部类名来创建对象
(6) 枚举类(Enum Class)
枚举类用于定义一组常量。它可以用于表示固定的常量集,如一周的天数、方向等。
enum Day {
MONDAY, TUESDAY, WEDNESDAY;
}
public class Main {
public static void main(String[] args) {
Day monday = Day.MONDAY;
Day tuesday = Day.TUESDAY;
Day wednesday = Day.WEDNESDAY;
switch (monday) {
case MONDAY:
System.out.println("Monday.");
break;
case TUESDAY:
System.out.println("TUESDAY.");
break;
case WEDNESDAY:
System.out.println("WEDNESDAY.");
break;
default:
System.out.println("NULL day.");
}
}
}
作用:用于定义常量的集合,如一周的天数、月份、方向等
-
枚举类的所有实例都是常量,且在类加载时就被初始化
-
可以有构造器、方法和字段
4.类的成员?
使用static修饰的成员方法和成员变量称之为类成员。
使用static修饰的成员变量叫做类变量。
使用static修饰的成员方法叫做类方法。
未使用static修饰的成员方法和成员变量称为实例成员
未使用static修饰的成员变量叫做实例变量
未使用static修饰的成员方法叫做实例方法
public class Main {
public String name; //实例变量
public static int age; //类变量
public void init(){
//实例方法
}
public static void end(){
//类方法
}
}
实例变量和类变量的区别:
所有该类的对象共享同一个类变量,但是每个对象都会有自己独特的实例变量
所有该类的对象都能改变类变量的值,但是每个对象只能改变自己的实例变量值
- 实例变量在使用前必须创建一个对象,根据对象名.变量名使用,但是类变量不需要创建对象
类方法和实例方法的区别:
所有该类对象共享类方法和实例方法
类方法使用类名.方法名(参数)调用即可,不需要实例化对象后使用
实例方法使用对象名.方法名(参数)调用
二、Java中类的使用
1.类的使用定义
使用class关键字定义的均属于是类。
public class Person {
//这就定义好了Person这个类
//这个类中就可以定义属性和行为
//这里可以写成员变量和成员方法
}
2.类中成员变量声明
什么是成员变量?在类中定义的变量均属于是成员变量,还可以直接赋值。
public class Person {
//这就定义好了Person这个类
//这里可以写成员变量和成员方法
//这里均是可以自定义的哟
String name; //名字
int age; //年龄
int phone; //电话
int gender; //性别 性别使用int型来表示 1男 0女
//以上定义是类的属性
}
3.类中成员方法声明
public class Person {
//这就定义好了Person这个类
//这里可以写成员变量和成员方法
//
String name; //名字
int age; //年龄
int phone; //电话
int gender; //性别 性别使用int型来表示 1男 0女
public void test(){ //成员方法
System.out.println("姓名:"+name);
System.out.println("年龄:"+age);
System.out.println("电话:"+phone);
System.out.println("性别:"+gender);
}
//在主方法中调用这个方法即可输出内容
}
4.创建对象
可以使用类创建对象
语法:
变量名 = new 类类型名();
public class Person {
//这就定义好了Person这个类
//这里可以写成员变量和成员方法
//
String name; //名字
int age; //年龄
int phone; //电话
int gender; //性别 性别使用int型来表示 1男 0女
public void test(){ //成员方法
System.out.println("姓名:"+name);
System.out.println("年龄:"+age);
System.out.println("电话:"+phone);
System.out.println("性别:"+gender);
}
//主方法中创建对象直接调用使用
public static void main(String[] args) {
Person per = new Person(); //创建对象
per.name = "小安"; //初始化
per.age = 24;
per.phone = 1845453244;
per.gender = 1;
per.test(); //调用类中方法
//当调用方法时可以传入参数的,这里是不需要参数所以没有传参数
}
}
运行结果:
三、方法重载和方法重写
1.方法重载(Overload)
定义:在同一个类中有相同的方法名但是有不同的参数列表,就表示为方法重载。
注意喽!!!和返回类型是没有关系的哟
注意事项:每个重载的方法(或者构造函数)都必须有一个独一无二的参数类型列表。最常用的地方就是构造器的重载。
// 两个整数相加 int型数相加
int add(int num1,int num2){
return num1 + num2;
}
// 两个整数相加 float浮点型相加
float add(float num1,float num2){
return num1 + num2;
}
// 两个整数相加 double浮点型相加
double add(double num1,double num2){
return num1 + num2;
}
//三个方法的名字都是相同的,但是需要传入的参数不同,这样就是方法的重载
2.方法重写(Override)
本来重写需要到后面的继承才和大家了解,但是也可以先了解了解基础,哈哈哈
定义:重写是子类对父类的允许访问的方法的实现过程进行重新编写, 返回值和形参都不能改变。即外壳不变,核心重写!
好处:重写的好处在于子类可以根据需要,定义特定于自己的行为。 也就是说子类能够根据需要实现父类的方法。
//重写发生在继承关系中
class Dog{
public void bark(){
System.out.println("woof");
}
}
class Hound extends Dog{
public void sniff(){
System.out.println("sniff");
}
public void bark(){
System.out.println("bow1");
}
}
3.方法重载和方法重写区别
(1)方法重载是一个类中定义了多个方法名相同,而他们的参数的数量不同或数量相同而类型和次序不同,则称为方法的重载(Overloading)。
(2)方法重写是在子类存在方法与父类的方法的名字相同,而且参数的个数与类型一样,返回值也一样的方法,就称为重写(Overriding)。
(3)方法重载是一个类的多态性表现,而方法重写是子类与父类的一种多态性表现。
图解更容易了解
4.构造方法使用
定义:Java语言通过类的构造方法构建对象,构造方法与普通方法的声明类似,但是构造方法有一些特征:构造器的名称必须与类名相同。
作用:一般用来初始化成员属性和成员方法的,即new对象产生后,就调用了对象的属性和方法。构造函数是对象一建立就运行,给对象初始化,就包括属性,执行方法中的语句。
public class Student {
//学生类
String name;
public Student(){ //这就是一个无参构造方法
System.out.println("这就是无参构造方法");
}
public Student(String name){ //这就是有参构造方法
System.out.println("这就是有参构造方法");
}
//在new对象的时候就可以直接传值
Student stu = new Student("小安");
}
使用场景:构造方法除了用于实例化对象之外,可以通过构造方法为成员变量赋值。
四、类的修饰符、控制符
1.非访问控制符
this关键字:指代当前对象实例
this是一种特殊的引用,指向当前对象
如果发生局部变量可以成员变量命名冲突时,可以通过this.成员变量名的方式区分实例变量和局部变量。
一个构造方法中需要调用同一个类的另一个构造方法,可以通过this()的方式调用,但this()必须要书写在第一行。
public class Student {
//学生类
String name;
// 当传入一个name值后,我们需要把这个值传到全局变量内使用
// 如果不加this,则name将会与这个方法里面的name进行匹配赋值,因为在方法内是属于局部变量
// 所以我们在接收变量前加上this关键字后,指的就是全局变量
public Student(String name){
this.name = name;
}
}
static关键字:表示类级别的成员(属性和方法)
静态的,非实例的,类的可以修饰内部类,也可以修饰成员
static关键字:
Java类提供了两种类型的变量,用static关键字修饰的静态变量和不用static关键字修饰的实例变量。
静态变量属于类,在内存中只有一个复制,只要静态变量所在的类被加载。
静态变量就会被分配空间,因此就可以被使用了。对静态变量的引用有两种方式,分别是“类.静态变量"和”对象.静态变量"
static成员方法:
static方法是类的方法,不需要创建对象就可以被调用,而非static方法是对象的方法,只有对象被创建出来后才可以被使用。static方法中不能使用this和super关键字,不能调用非static方法,只能访问所属类的静态成员变量和成员方法,因为当static方法被调用时,这个类的对象可能还没被创建,即使已经被创建了,也无法确定调用哪个对象的方法。
static用处:
修饰成员变量
修饰成员方法
静态代码块
修饰类【只能修饰内部类也就是静态内部类】
静态导包
static注意事项:
静态只能访问静态,非静态既可以访问非静态的,也可以访问静态的。
public class Student {
static Integer id; //学号
static String name; //姓名
Student(Integer id,String name){
this.id = id;
this.name = name;
}
}
class Person {
public static void main(String[] args) {
Student stu = new Student(10001, "小安");
System.out.println(stu.id); //用一个实例化的对象来访问类中static字段
System.out.println(stu.name);
System.out.println(Student.id); //这里可以用类名来直接访问类中static字段
System.out.println(Student.name);
}
}
final关键字:表示不可修改的常量或不可继承的类/不可重写的方法
最终的,不可改变的可以修饰类,成员,局部变量
final类:如果一个类被final修饰符所修饰和限定,说明这个类不能被继承,即不会拥有子类。
final方法:final修饰符所修饰的方法,是不能被子类所覆盖的方法。
final字段和final局部变量:它们的值一旦给定,就不能更改。并且它们是只读量,它们能且只能被赋值一次,不能多次赋值。
如果一个字段被 static final 同时修饰时,它可以表示常量。如果不给定初始值,则按默认值进行初始化(数值为0,boolean类型为false,引用类型为null)。
public class TestClass {
public static void main(String[] args) {
MyClass myClass1 = new MyClass();
MyClass myClass2 = new MyClass();
System.out.println(myClass1.i);
System.out.println(myClass1.j);
System.out.println(myClass2.i);
System.out.println(myClass2.j);
}
}
class MyClass{
public final double i = Math.random(); //用final修饰的
public static double j = Math.random(); //用static修饰
}
abstract关键字:抽象的,不可实例化的可以修饰 类,成员
凡是用abstract修饰符修饰的类被称为抽象类。
抽象类不能被实例化。
抽象类方法在子类中必须被实现,否则子类仍然是abstract的。
1.用abstract关键字来表达的类,其表达式为:(public) abstract class 类名{ ... }
2.抽象类不能实例化,我们没法直接new一个抽象类。抽象类的本身就代表了一个类型,无法具体确定为一个具体的对象,只有他的继承类可以被实例化。
3.抽象类虽然不能被实例化,但有自己的构造方法。
4.抽象类与接口(interface)有很大的不同之处,接口中不能有实例方法去实现业务逻辑,而抽象类中可以有实例方法,并实现业务逻辑。
5.抽象类不能用final关键字修饰。
优点:
由于抽象类不能被实例化,最大的好处就是通过方法的覆盖来实现多态的属性。也就是运行期绑定。
抽象类将事物的共性的东西提取出来,由子类继承去实现,代码易扩展、易维护。
简单的例子:
//员工实体类
public abstract class Employee {
private int id;
private String name;
private int age;
public Employee(int id, String name,int age) {
this.id=id;
this.name = name;
this.age =age;
}
public int getId() {
return this.id;
}
public String getName() {
return this.name;
}
public int getAge() {
return this.age;
}
public abstract double getSalary();
}
//工资实体类
public class Salary extends Employee {
private double salary;
public Salary(int id,String name,int age,double salary) {
super(id,name,age);
setSalary(salary);
}
public void setSalary(double salary) {
this.salary = salary;
}
public double getSalary(){
return this.salary;
}
}
public class Test {
public static void main(String[] args) {
//通过自身的非抽象子类来实例化对象
Employee a=new Salary(1,"小安",25,3600.00);
//非抽象子类可以实例化对象
Salary b=new Salary(2,"小王",30,4500.00);
System.out.println("第"+a.getId()+"个,姓名为:"+a.getName()+", 年龄为:"+a.getAge()+", 工资为:"+a.getSalary());
System.out.println("第"+b.getId()+"个,姓名为:"+b.getName()+", 年龄为:"+b.getAge()+", 工资为:"+b.getSalary());
}
}
运行结果:
2.可访问修饰符
(1)public: 所有类可见
访问范围最广,一般都可以访问
(2)protected: 同包或子类可见
可以在同一个类中,同一个包中,和不同包中的子类中被访问
(3)default (默认): 同包可见
如果不加修饰符,则只能在同一个类和同一个包中,这2种情况下访问:
类的访问控制符为public或者默认,如果类用public修饰,则该类可以被其他类所访问,如果类是默认访问控制符,则该类只能被同包中的类访问。
(4)private: 仅本类可见
只能在同一个类中被访问