目录
类和对象的初步认识
对象和类其实都是个很抽象的概念
C语言是面向过程的,关注的是过程,分析出求解问题,通过函数调用逐步解决问题。
java是基于面向对象的,关注的是对象,将一件事情拆分成不同的对象,靠对象之间的互相完成。
打个比方 将大象放进冰箱
面向过程:注重过程,在整个过程中设计的行为,就是功能。
1.把冰箱打开 2.把大象放入 3.把冰箱关起来
面向对象:注重对象,也就是参与过程涉及到的主体,是通过逻辑将一个个功能实现连接起来的
打开冰箱,储存,关闭都是对冰箱的操作,是冰箱的行为。
找对象 创建对象 适用对象
冰箱就是一个1对象,所以只要操作所具备的功能,都要定义在冰箱中。
类和类的实例化
对象从类而来
总的来说:类相当于一个模板,对象是由模板产生的样本,一个类,可以产生无数个对象。
//创建类
class<class_name>{
field;//成员属性
method://成员方法
}
//实例化对象
<class_name><对象名>=new <class_name>();
class Person{
//字段-》属性-》成员变量
public String name ="xinyouye";
public int age =18;
//方法->行为
public void eat() {
System.out.println(name+"正在吃饭");
}
public void sleep(){
System.out.println(name+"正在睡觉");
}
}
由类产生对象的过程,叫做实例化
1.类只是一个模型一样的东西
2.一个类可以实例化出多个对象,实例化出的对象,占用实际的物理空间,储存类成员变量
3.类实例化处对象就像现实中使用建筑设计图建造出的房子,类就像是设计图
class Prson{
public int age;
public String name;
public String sex;
public void eat(){
Syste.out.println("吃饭!");
}
public void sleep(){
System.out.println("睡觉!");
}
}
public static void main(String[] args){
Person person = new Person();
person.eat()
Person.sleep();
//产生对象 实例化对象
person person2 = new Person();
person person3 = new Person();
}
}
输出结果为
吃饭
!
睡觉
!
注:
new关键字用于创建一个对象的是列
使用 来访问对象中的属性和方法
同一个类可以创建多个实例
通过new关键词
public class TestDemo{
public static void main(String[]args){
//Person person = null;
Person person = new Person();
}
3.类的成员
包含:字段,方法,代码块,内部类和接口。
3.1字段/属性/成员变量
注:
"
访问
"
既包含读
,
也包含写
.
对于一个对象的字段如果没有显式设置初始值
,
那么会被设置一个默认的初值
.
默认值规则
对于各种数字类型,
默认值为
0.
对于
boolean
类型
,
默认值为
false.
对于引用类型
(String, Array,
以及自定制类
),
默认值为
null
认识
null
null
在
Java
中为
"
空引用
",
表示不引用任何对象
.
类似于
C
语言中的空指针
.
如果对
null
进行
class Person{
public String name;
public int age;
}
class Test{
public static void main(String[] args){
Person person = new Person();
System.out.println(person.name.length());//获取字符串长度
}
}
//执行结果
Exceptioninthread"main"java.lang.NullPointerException
atTest.main(Test.java:9)
字段就地初始化
很多时候我们不希望字段使用默认值, 而是需要我们显式设定初值. 可以这样写
classPerson {
publicStringname="张三";
publicintage=18;}
classTest {
publicstaticvoidmain(String[] args) { Personperson=newPerson();
System.out.println(person.name);
System.out.println(person.age);
}
}
// 执行结果张三
18
3.2方法(method)
就是我们曾经讲过的方法
.
用于描述一个对象的行为
class Person{
public int age = 18;
public String name = "张三";
public void show(){
System.out.println("我叫"+name+",今年"+age+"岁");
}
}
classTest {
publicstaticvoidmain(String[] args) { Personperson=newPerson();
person.show();
}
}
// 执行结果
我叫张三, 今年18岁
3.3 static 关键字
1.修饰属性
2.修饰方法
3.代码块
4.修饰类
1.修饰属性
classTestDemo{
publicinta;
publicstaticintcount;}
publicclassMain
publicstaticvoidmain(String[] args) { TestDemot1=newTestDemo();
t1.a++;
TestDemo.count++;
System.out.println(t1.a);
System.out.println(TestDemo.count); System.out.println("============"); TestDemot2=newTestDemo();
t2.a++;
TestDemo.count++;
System.out.println(t2.a);
System.out.println(TestDemo.count); }
}
输出结果为
1
1
============1
2
2.修饰方法
如果在任何方法上应用
static
关键字,此方法称为静态方法
静态方法属于类,而不属于类的对象。
可以直接调用静态方法,而无需创建类的实例。
静态方法可以访问静态数据成员,并可以更改静态数据成员的值。
classTestDemo{
publicinta;
publicstaticintcount;
publicstaticvoidchange() {
count=100;
//a = 10; error 不可以访问非静态数据成员 }
}
publicclassMain{
publicstaticvoidmain(String[] args) {
TestDemo.change();//无需创建实例对象就可以调用 System.out.println(TestDemo.count);
}
}
输出结果
100
注:
1>
静态方法不能直接使用非静态数据成员或调用非静态方法
(
非静态数据成员和方法都是和实例相关的
).
this
和
super
两个关键字不能在静态上下文中使用
(this
是当前实例的引用
, super
是当前实例父类实例的引用
,
也
是和当前实例相关
).
2>
我们曾经写的方法为了简单
,
都统一加上了
static.
但实际上一个方法具体要不要带
static,
都需要是情形而定
.
main
方法为
static
方法
.
3.4小结
classPerson {
publicintage;//实例变量 存放在对象内
publicStringname;//实例变量
publicStringsex;//实例变量
publicstaticintcount;//类变量也叫静态变量,编译时已经产生,属于类本身,且只有一份。存放在方法区 publicfinalintSIZE=10;//被final修饰的叫常量,也属于对象。被final修饰,后续不可更改
publicstaticfinalint COUNT=99;//静态的常量,属于类本身,只有一份被final修饰,后续不可更改
//实例成员函数
publicvoideat() {
inta=10;//局部变量
System.out.println("eat()!");
}
//实例成员函数
publicvoidsleep() {
System.out.println("sleep()!");
}
//静态成员函数
publicstaticvoidstaticTest(){
//不能访问非静态成员
//sex = "man"; error
System.out.println("StaticTest()");
}
}
publicclassMain{
Publicstaticvoidmain(String[] args) {
//产生对象实例化对象
Personperson=newPerson();//person为对象的引用
System.out.println(person.age);//默认值为0
System.out.println(person.name);//默认值为null
//System.out.println(person.count);//会有警告!
//正确访问方式:
System.out.println(Person.count);
System.out.println(Person.COUNT);
Person.staticTest();
//总结:所有被static所修饰的方法或者属性,全部不依赖于对象。 person.eat();
person.sleep();
}
}
//输出结果为:
0
null
0
99
StaticTest()eat()!
sleep()!
4.封装
什么叫封装
?
<<
代码大全
>>
开篇就在讨论一个问题
:
软件开发的本质就是对程序复杂程度的管理
.
如果一个软件代码复杂程
度太高
,
那么就无法继续维护
.
如何管理复杂程度
?
封装就是最基本的方法
.
在我们写代码的时候经常会涉及两种角色
:
类的实现者
和
类的调用者
.
封装的本质就是让类的调用者不必太多的了解类的实现者是如何实现类的
,
只要知道如何使用类就行了
.
这样就降低了类使用者的学习和使用成本
,
从而降低了复杂程度
.
4.1 private实现封装
被
public
修饰的成员变量或者成员方法
,
可以直接被类的调用者使用
.
被
private
修饰的成员变量或者成员方法
,
不能被类的调用者使用
.
换句话说
,
类的使用者根本不需要知道
,
也不需要关注一个类都有哪些
private
的成员
.
从而让类调用者以更低的
成本来使用类
.
直接使用
public
classPerson {
publicStringname="张三";
publicintage=18;
}
classTest {
publicstaticvoidmain(String[] args) {
Personperson=newPerson();
System.out.println("我叫"+person.name+", 今年"+person.age+"岁"); }
}
// 执行结果
我叫张三, 今年18岁
这样的代码导致类的使用者
(main
方法的代码
)
必须要了解
Person
类内部的实现
,
才能够使用这个类
.
学习成本较
高
一旦类的实现者修改了代码
(
例如把
name
改成
myName),
那么类的使用者就需要大规模的修改自己的代码
,
维护成本较高.
范例:使用
private
封装属性
,
并提供
public
方法供类的调用者使用
.
class Person {
private String name = "张三"; private int age = 18;
public void show() {
System.out.println("我叫" + name + ", 今年" + age + "岁"); }
}
class Test {
public static void main(String[] args) { Person person = new Person();
person.show();
}
}
// 执行结果
我叫张三, 今年18岁
注意事项
private
不光能修饰字段
,
也能修饰方法
通常情况下我们会把字段设为
private
属性
,
但是方法是否需要设为
public,
就需要视具体情形而定
.
一般我们希
望一个类只提供
"
必要的
" public
方法
,
而不应该是把所有的方法都无脑设为
public.
4.2 getter和setter方法
代码示例
class Person {
private String name;//实例成员变量 private int age;
public void setName(String name){
//name = name;//不能这样写
this.name = name;//this引用,表示调用该方法的对象 }
public String getName(){
return name;
}
public void show(){
System.out.println("name: "+name+" age: "+age); }
}
public static void main(String[] args) {
Person person = new Person();
person.setName("caocao");
String name = person.getName();
System.out.println(name);
person.show();
}
// 运行结果
caocao
name: caocao age: 0
注:
getName
即为
getter
方法
,
表示获取这个成员的值
.
setName
即为
setter
方法
,
表示设置这个成员的值
.
当
set
方法的形参名字和类中的成员属性的名字一样的时候,如果不使用
this,
相当于自赋值
. this
表示当前实例
的引用
.
不是所有的字段都一定要提供
setter / getter
方法
,
而是要根据实际情况决定提供哪种方法
.
在
IDEA
中可以使用
alt + insert (
或者
alt + F12)
快速生成
setter / getter
方法
.
在
VSCode
中可以使用鼠标右键
菜单
->
源代码操作中自动生成
setter / getter
方法
.
5. 构造方法
5.1 基本语法
构造方法是一种特殊方法
,
使用关键字
new
实例化新对象时会被自动调用
,
用于完成初始化操作
.
new
执行过程
语法规则
1.
方法名称必须与类名称相同
2.
构造方法没有返回值类型声明
3.
每一个类中一定至少存在一个构造方法(没有明确定义,则系统自动生成一个无参构造)
注意事项
如果类中没有提供任何的构造函数,那么编译器会默认生成一个不带有参数的构造函数
若类中定义了构造方法,则默认的无参构造将不再生成
.
构造方法支持重载
.
规则和普通方法的重载一致
.
代码示例
class Person {
private String name;//实例成员变量 private int age;
private String sex;
public Person() {
this.name = "caocao";
this.age = 10;
this.sex = "男";
}
//带有3个参数的构造函数
public Person(String name,int age,String sex) { this.name = name;
this.age = age;
this.sex = sex;
}
public void show(){
System.out.println("name: "+name+" age: "+age+" sex: "+sex); }
}
public class Main{
public static void main(String[] args) {
Person p1 = new Person();//调用不带参数的构造函数如果程序没有提供会调用不带参数的构造函数 p1.show();
Person p2 = new Person("zhangfei",80,"男");//调用带有3个参数的构造函数
p2.show();
}
}
// 执行结果
name: caocao age: 10 sex: 男
name: zhangfei age: 80 sex: 男
5.2 this关键字
class Person {
private String name;//实例成员变量 private int age;
private String sex;
public Person() {
//this调用构造函数
this("bit", 12, "man");//必须放在第一行进行显示 }
//这两个构造函数之间的关系为重载。
public Person(String name,int age,String sex) { this.name = name;
this.age = age;
this.sex = sex;
}
public void show() {
System.out.println("name: "+name+" age: "+age+" sex: "+sex); }
}
public class Main{
public static void main(String[] args) {
Person person = new Person();//调用不带参数的构造函数
person.show();
}
}
// 执行结果
name: bit age: 12 sex: man
6. 认识代码块
1.
就地初始化
2.
使用构造方法初始化
3.
使用代码块初始化
前两种方式前面已经学习过了
,
接下来我们介绍第三种方式
,
使用代码块初始化
6.1 什么是代码块
普通代码块
构造块
静态块
同步代码块(后续讲解多线程部分再谈)
6.2 普通代码块
public class Main{
public static void main(String[] args) { { //直接使用{}定义,普通方法块
int x = 10 ;
System.out.println("x1 = " +x); }
int x = 100 ;
System.out.println("x2 = " +x);
}
}
// 执行结果x1 = 10
x2 = 100
6.3 构造代码块
构造块:定义在类中的代码块
(
不加修饰符
)
。也叫:
实例代码块
。构造代码块一般用于初始化实例成员变量。
class Person{
private String name;//实例成员变量 private int age;
private String sex;
public Person() {
System.out.println("I am Person init()!"); }
//实例代码块
{
this.name = "bit";
this.age = 12;
this.sex = "man";
System.out.println("I am instance init()!"); }
public void show(){
System.out.println("name: "+name+" age: "+age+" sex: "+sex); }
}
public class Main {
public static void main(String[] args) { Person p1 = new Person();
p1.show();
}
}
// 运行结果
I am instance init()!
I am Person init()!
name: bit age: 12 sex: man
使用
static
定义的代码块。
一般用于初始化静态成员属性
class Person{
private String name;//实例成员变量
private int age;
private String sex;
private static int count = 0;//静态成员变量
public Person(){
System.out.println("I am Person init()!"); }
//实例代码块
{
this.name = "bit";
this.age = 12;
this.sex = "man";
System.out.println("I am instance init()!"); }
//静态代码块
static {
count = 10;//只能访问静态数据成员
System.out.println("I am static init()!"); }
public void show(){
System.out.println("name: "+name+" age: "+age+" sex: "+sex); }
}
public class Main {
public static void main(String[] args) {
Person p1 = new Person();
Person p2 = new Person();//静态代码块是否还会被执行? }
}
注意事项
静态代码块不管生成多少个对象,其只会执行一次,且是最先执行的。
静态代码块执行完毕后
,
实例代码块(构造块)执行,再然后是构造函数执行