面向对象的定义
C语言是一门面向过程的语言,讲究按照任务的完成顺序进行代码编排,从而将事情解决。而Java是一门面对对象编程的语言,讲究完成任务的各事物之间的联系,通过他们之间相互交互从而解决问题
类的定义
类是构成对象的蓝图,通过类的描述,可以了解构造对象的属性与功能,类和C语言中的结构体类似
class ClassName{
field; //成员变量
method; //成员方法
}
标准:
类名用大驼峰(构成类名的每一个英文单词都大写)进行定义
成员前都写public(后续解释)
方法不带static(后续解释)
一个文件只定义一个类
main方法所在的类用public修饰
public修饰的类必须和文件名相同
不要随意修改类名
类的实例化
即创建对象的过程
类名 对象名 = new 类名();
我们可以通过对象名.方法名对对象的方法进行访问,可以用对象名.属性对对象的属性进行访问。
实际上,类只是一个图纸,对象就如同通过图纸构造的switch游戏机,每一个游戏机都有自己的型号(属性),也有属于自己的游戏(方法)
this关键字
当我们创建方法时,想要为类的属性进行赋值,这时可能出现局部变量与成员变量同名的情况,在这种情况下Java默认使用的都是局部变量。便需要我们用this关键字
this.成员变量代表访问当前对象的成员变量
this只能在成员方法中使用
对象的初始化
对于之前讲的局部变量,如果没有初始化就使用,那么程序会报错,而如果是构造的对象,那么各种类型如果不初始化就默认使用各种0,可以参考数组那一章的表格
如果我们想要给对象的属性赋值,那么需要调用setXXX的方法,这样做非常麻烦。那么以下方法,便是在对象的构造过程中就将初值赋值
构造方法
这是一个特殊的方法,名字必须与类名相同,没有返回值,一般用public修饰
public class Date {
public int year;
public int month;
public int day;
public Date(int year, int month, int day){
this.year = year;
this.month = month;
this.day = day;
}
}
构造方法可以重载
如果用户没有写构造方法,那么编译器会自动生成一份无参的构造方法,但如果用户写了,编译器便不再生成
public class Date {
public int year;
public int month;
public int day;
public Date(){
this(1900, 1, 1);
}
public Date(int year, int month, int day) {
this.year = year;
this.month = month;
this.day = day;
}
}
我们可以用上面这种this(xx)的形式来调用另外一种构造方法,像上述代码便是调用带有三个参数的构造方法
需要注意的是:
this()必须是构造方法中的第一条语句
不能形成环
封装
就是将对象的属性进行隐藏,仅公开一些方法,防止外界直接篡改对象的属性
访问限定符
像之前的public便是一个访问限定符,具体如下
范围 | private | default | protected | public |
---|---|---|---|---|
同一包中同一类 | √ | √ | √ | √ |
同一包中不同类 | √ | √ | √ | |
不同包中的子类 | √ | √ | ||
不同包中的非子类 | √ |
default指的是什么都不写的时候的权限
其他部分将在后面的继承部分讲解
通过把成员变量设置为private,可以将对象封装
自定义包
在文件的最上方加上一个 package 语句指定该代码在哪个包中
包名需要尽量指定成唯一的名字, 通常会用公司的域名的颠倒形式
包名要和代码路径相匹配
如果一个类没有 package 语句, 则该类被放到一个默认包中
如果两段代码在不同的包中,其访问权限就如上面的表中所示
static
修饰成员变量
若想要不同的对象拥有同一份相同的属性,那么将用到static关键字
被static修饰的成员是静态成员,不属于某个具体的对象,是所有对象共享的
可以通过对象访问,也可以直接通过类名访问
其生命周期伴随类的一生
初始化:
1.定义时给出初始值
2.静态代码块初始化(具体方法参照下面的代码块部分)
修饰成员方法
和静态成员一样,静态的成员方法属于类的方法,不是对象特有的,静态成员一般通过静态方法访问
public class Student{
private static String classRoom = "5";
public static String getClassRoom(){
return classRoom;
}
}
public class TestStudent {
public static void main(String[] args) {
System.out.println(Student.getClassRoom());
}
}
需要注意的是:
静态方法中不能访问非静态成员变量(因为静态方法不依赖于对象,没有对象就没有非静态成员变量)
静态方法中也不能调用非静态方法,因为非静态方法中有this参数,其依赖于对象
静态方法无法重写(后续讲解)
代码块
普通代码块
用{}包裹的就是普通代码块
构造代码块
定义在类中的代码块,也叫实例代码块,用来初始化实例成员变量
静态代码块
{}前面用static修饰的代码块,用来初始化静态成员变量
public class Student{
private String name;
private int age;
private static String classRoom;
//实例代码块
{
this.name = "hehe";
this.age = 15;
System.out.println("instance init");
}
// 静态代码块
static {
classRoom = "5";
System.out.println("static init");
}
public Student(){
System.out.println("Student init");
}
public static void main(String[] args) {
Student s1 = new Student();
Student s2 = new Student();
}
}
通过执行上述代码,我们可以发现:
无论创建多少个对象,静态代码块都会只执行一次
静态成员变量是JVM加载类时开辟空间并初始化的
静态代码段如果有多个,那么将按照代码顺序执行
实例代码块只有创建对象了才会执行
内部类
将一个类定义在另一个类的内部
内部类和外部类共用同一个java源文件,但是经过编译之后,内部类会形成单独的字节码文件
根据内部类的定义位置,可以有如下分类
public class OutClass {
// 成员位置定义:未被static修饰:实例内部类
public class InnerClass1{
}
// 成员位置定义:被static修饰:静态内部类
static class InnerClass2{
}
public void method(){
// 方法中定义内部类:局部内部类
class InnerClass5{
}
}
}
实例内部类
实例内部类可以访问外部类的任意成员
如果外部类和内部类的成员名相同,则在内部类中优先访问内部类成员
访问外部类同名成员方法:
外部类名称.this.名字
内部类对象的创建
OutClass.InnerClass innerClass1 = new OutClass().new InnerClass();
//也可以先创建外部类对象,再创建内部类对象
OutClass outClass = new OutClass();
OutClass.InnerClass innerClass2 = outClass.new InnerClass();
//调用内部类方法
innerClass2.methodInner();
可以看出,实例内部类的对象创建前提是先创建外部类对象
静态内部类
静态内部类中只能访问外部的静态成员
创建静态内部类对象不依赖外部类对象
OutClass.InnerClass innerClass = new OutClass.InnerClass();
局部内部类
定义在外部类的方法中,并且只能在该方法中使用
局部内部类不能被public,static修饰
匿名内部类
后续章节讲解
toString
想要打印对象的相关属性,只需要重写toString方法
如果不写toString,那么print(对象名)将会打印对象的地址,重写后,将打印toString中返回的字符串
public class Person {
String name;
String gender;
int age;
public Person(String name, String gender, int age) {
this.name = name;
this.gender = gender;
this.age = age;
}
@Override
public String toString() {
return name + " " + gender + " " + age;
}
public static void main(String[] args) {
Person person = new Person("xiao","男", 18);
System.out.println(person);
}
}