01.面向对象简介
类相当于一个模板,是抽象的数据类型;对象相当于根据这个模板做出来的具体的东西,是类的实现。比如,Student这个类可以表示学生这个群体,而每个学生都是不一样的,故对象s1、s2、s3…即特定的学生有各自的特征属性比如身高、姓名等,但归根结底仍是学生,仍是基于Student这个模板创建出来的。
类具有自己的属性,如成员变量、成员方法等。再拿上面的例子来说,学生有各自的特征属性比如身高、姓名、成绩等,也可以有学习、吃饭、考试等行为,个人的属性与行为是不一样的,你可以考满分,我也可以挂科,但考试这个行为是学生这一群体即Student类所拥有的成员方法,成绩是Student的成员变量。
02.类的基本结构
成员变量
成员变量也叫成员属性。可以通过类创建的对象来进行访问和修改。成员变量默认有自己的初始值,也可以自己定义初始值
public class Student(){
String name;
int age; //成员变量
public static void main(String[] args){
Student s1 = new Student(); //通过 new + 构造方法 创建类的一个对象,Student s1 指 在内存中分配一个名叫s1的变量
s1.name = "电棍";
s1.age = 7; //通过 对象.成员变量 访问
}
成员方法
成员方法是一段语句的集合,是为了完成某件事而存在的。方法可以理解成C中的函数
格式:
[返回值类型] 方法名称([参数]){
//方法体
return 结果;
}
注意点:
非void方法中,return不一定需要放在最后,但任何情况都必须保证有返回值
int test(int a){
if(a > 0){
//此处必须要有return语句。
}
else{
return 0;
}
}
return语句会立即结束这个方法,return语句后面的代码将不会执行
void test(){
return; //方法结束
System.out.println("woc,bin!"); //不会执行
}
方法之间可以相互调用,也可以调用自己(递归)
int a(){
b();
}
int b(){
return b();
}
构造方法
构造方法是专门用来创建对象的方法,没有具体的返回值。可以理解成构造方法在为创建对象做准备,完成了构造方法的内容后,对象才会被创建。每个类中一定至少存在一个构造方法!!创建类后,若没有明确定义,这个类自带一个默认隐藏的无参构造方法
public class Test{
public Test(){
} //默认隐藏的无参构造方法
}
当然,也可以自定义构造方法,此时我们定义的构造会覆盖默认的无参构造。常用于给成员属性赋初始值
public class Student{
String name;
public Student(){
name = "小炫"; //创建的对象一开始都叫小炫
}
}
也可以自定义有参构造,同样会覆盖默认的无参构造。但通常会遇到形参与成员变量名称冲突的情况,此时需要this关键字,this指代当前对象,通过 this.成员变量 的形式 将形参age 赋给当前对象的age。
public class Student{
int age;
public Student(int age){
this.age = age;
}
}
构造方法名称必须与类名一致,首字母大写。若想同时保留无参构造与有参构造,可通过方法的重载实现(见方法的重载)
静态变量与静态方法
当一个类的所有对象同时拥有相同的属性时,为了节省内存的开销,不会特意去对每个对象分别声明实例变量,而是通过 static 关键字,来使得变量/方法变为静态。静态变量/方法是类具有的属性,是所有对象共享的,静态变量不需要实例化,用类访问就行了(也可以使用对象来调用但不推荐)
举个例子,现在需要一个学生信息系统,要求能够显示学生的姓名、学号和民族,假设学生全部都是汉族,那么就可以用静态变量 来避免每次创建对象时声明“民族”这一相同的实例变量
public class Main{
public static void main(String[] args){
Student s1 = new Student("田所浩二","114514");
System.out.println("姓名:" + s1.name + " 学号:" + s1.id + " 民族:" + Student.nationality);
//通过类访问静态变量nationality
Student s2 = new Student("乌兹", "2800");
System.out.println("姓名:" + s2.name + " 学号:" + s2.id + " 民族:" + Student.nationality);
}
}
class Student{
String name;
String id;
static String nationality = "汉";
public Student(String name, String id){ //有参构造
this.name = name;
this.id = id;
}
}
输出为:
姓名:田所浩二 学号:114514 民族:汉
姓名:乌兹 学号:2800 民族:汉
注:1)非静态成员方法可以访问静态成员方法、静态成员变量、非静态成员方法、非静态成员变量
2)静态只能访问静态
代码块与静态代码块
代码块在对象创建时执行,且先于构造方法。每创建一个对象,代码块执行一次。静态代码块在类刚加载时就会调用。
public class Student{
{
System.out.println("我是代码块");
}
public Student(){
System.out.println("我是构造方法");
}
}
输出为:
我是代码块
我是构造方法
03.方法的重载
重载,就是指方法名称相同,但参数不相同的情形。想要用到这个方法的时候,会根据所传参数自动调用对应的方法。还是上面学生的例子,分数可以是98这个int型,也可以是98.5这个double型,故不得不用到多个方法,而这些方法可以是同名的
public class Student{
int score;
void setScore(int score){
this.score = score;
}
void setScore(double score){
this.score = score;
}
} //重载方法返回值可以不同,形参一定不同!!如果仅返回值不同而形参相同,呵呵 :)
04.数组类型
一维数组
一维数组中,元素是依次排列的,可通过下标(0~)访问每个元素。与C语言不同,Java中的数组不需要手动设置默认值。可以通过 数组名.length 来获取数组长度,数组的长度在创建时就固定下来了,不可更改。数组本身就是个类,有自己的成员变量(如.length)和成员方法(如.toString())
类型[] 变量名称 = new 类型[数组大小]
int[] arr = new int[10];
arr[0] = 4396;
System.out.println(arr[0]); //输出为4396
System.out.println(arr[1]); //输出为0
System.out.println(arr.length); //输出为10
二维数组
二维数组,可以理解成数组的数组,每一个元素存放一个数组的引用。先看格式:
int[][] arr = new int[3][2]
//为方便叙述,特殊化{{1,2},{3,4},{5,6}}
对于 int [ ] [ ] 可以把 int [ ] 看成一个整体,可以当做一个数组类型,那么 (int [ ]) [ ] 就是一个一维数组了,只不过该一维数组中的每个元素就是我们前面视为整体的int [ ] 。更直观的说,int [3] [2] 中的[2] 表示一个有两个元素的一维数组,而这两个元素类型是int[3] ,也即{1,3,5}和{2,4,6}这两个一维数组,只不过是竖着排而已。
多维数组
同前
05.String和StringBuilder类
Java中的字符串类型不是int、char之类的基本数据类型,而是引用数据类型,本质是一个类。String支持重载,可以通过 + 运算符直接对两个String对象进行拼接并形成一个新的String对象。由于字符串在实际开发中使用很频繁,故将其放入方法区的字符串常量池中。Java中规定,双引号括起来的字符串是不可变的,“若子”始终是“若子”,不会变成“小炫”或“电棍”
//方法1
String str1 = "别吵别吵别吵,";
String str2 = "这里很关键你别搞事啊";
String str = str1 + str2; //创建3个对象,费时费空间,坏!
//方法2
String str = "别吵别吵别吵," + "这里很关键你别搞事啊"; //相比于上面的方法,只创建了一个对象,省时省空间,好!
方法2中出现了多个字符串的拼接,其实String已经被编译器优化成StringBuilder了。StringBuilder也是个类,能够存储可变长度的字符串
StringBuilder builder = new StringBuilder("good");
str.append(" morning"); //通过append关键字增加字符串内容
String str = builder.toString();
System.out.println(str); //输出为 good morning
06.访问控制
变量、方法和类之前通常会有public、private等关键词修饰,这一类关键词就是权限控制符。权限控制符可以防止外部类访问调用类内部的属性或方法,起到一个保护的作用。一个.java文件中有且仅有一个public类,且要求该类名与文件名相同,如
//文件:Student.java
public class Student{ //类名只有与文件名相同才能用public
private int age = 19; //由private修饰,只能类内部访问
}
class Test{ //不能用public修饰!!(此时为default访问状态)
}
//文件:Main.java
public class Main{
public static void main(String[] args){
Student s = new Student();
System.out.println(s.age); //此处能访问age吗?不能,age只能Student类内部访问!
}
}
Java中一共有四个访问控制符,分别为public 、protected 、normal 和 private,权限由高到低。类中限定为public的成员可以被所有的类访问;类中限定为protected的成员,可以被这个类本身、它的子类(包括同一个包中以及不同包中的子类)和同一个包中的所有其他的类访问;如果成员前不加任何权限控制符,则其属于默认default访问状态;private修饰的只能被类内部访问。(子类在08.继承中讲到。default访问状态时,前面不需要加default关键字!!default关键字不是这么用的!!)
07.包
Java中的包(package)是为方便管理组织Java文件的目录结构,也可以理解成分门别类存放类的文件夹。比如com.person.Student就表示Student类存储在com文件夹中的person文件夹。不同包内的类名可以相同
package com.test; //声明包
public class Test{
}
如果想访问不同包中的类,就需要导入包。不在同一包下的类是不能直接访问的,需要用 import 关键字导入(可以理解成C中的include)
import java.lang.*; //Java默认导入的包,不需要我们特意去声明
import com.person.Student; //此时可以直接访问Student类
import com.person.* //*表示可以直接访问该包下的所有类
静态导入支持对导入包中类的静态方法、静态变量进行直接调用。
//定义一个类 com/person/Student.java
package com.person;
public class Student(){
public static int a(){
return 1;
}
}
//文件:Main.java
import static com.person.Student.*; //静态导入Student类
public class Main{
public static void main(){
System.out.println(a()); //输出为1,直接调用Student类中的静态方法a()
}
}
后记
放假之后我的电子杨伟又发作了,玩什么都提不起劲来,大表哥2玩了三四个小时,丝毫感受不到其中的乐趣。突然想起了一两个月前因复习课内内容而搁置一旁的Java,便又继续了。几天后发现,我疑似是陷入快餐式的学习了,具体表现为看视频时 啊 懂得都懂,一旦自己上手,我是谁?我在干什么?恰巧看到了平时喜欢往课程群里转些公众号文章的材料力学老师 转发了一个什么 费曼学习法。其认为,学习分为主动学习和被动学习,被动学习包括听讲、阅读、试听等,占总学习的30%,而主动学习又包括讨论、实践以及学习效果最好的 教授给其他人。
于是就有了上面这个学习笔记。目的是为了巩固我的知识体系,同时增加了自己个人的一些理解,希望也能够帮助和我一样的萌新更好地理解。干这东西比我想象的要累,因为要对自己说过的话负责,不能去误导别人,对吧?所以每到一个知识点,我就搜一下,看看与自己理解的偏差有多大。上面这么个寥寥3k字的笔记,花了我三个晚上差不多9个小时,关键是连面向对象的三大特性都没到!!
但愿这个东西能够帮助一些人,但愿这个东西能够时刻提醒我该学了,也欢迎各位佬指正,也欢迎交流。如果有一天你发现这个节目停更了,那一定是我的电子杨伟痊愈了。抱拳!