目录
简介
-
封装性:内部的操作对外部而言不可见
继承性:在上一辈的基础上继续发展
多态性:在可控范围内的状态改变 -
OOA(面向对象分析)
OOD(面向对象设计)
OOP(面向对象编程)
面向对象的特征:可以进行生活的抽象
类与对象
- 声明并实例化对象:类名称 对象名称 = new 类名称();
-
对象只有实例化(new)以后才可以真正使用
-
引用类型指的是内存空间的操作:
- 堆内存空间:保存真正的数据,保存的是属性信息
- 栈内存空间:保存的堆内存的地址,堆内存的操作权
-
一个栈内存只能保存一个堆内存地址
一块堆内存可以被多个栈内存所指向 -
NullPointerException:只有引用数据类型才会产生此类异常
-
垃圾空间:指的是没有任何栈内存指向的堆内存空间,所有垃圾空间将定期被Java的垃圾收集器进行回收,以实现内存空间的释放
private实现封装处理
- 使用private声明后属性安全了,如果想要进行private私有属性的访问,按照Java设计原则,可使用setter、getter方法:
- setter方法:主要用于进行属性内容的设置 / 修改
- getter方法:主要用于属性内容的取得
构造方法与匿名对象
-
可以利用构造方法传递属性的内容(初始化),以避免重复的setter调用
-
匿名对象:
如,new Person("Bob",30).getName()
由于匿名对象不会有任何的栈内存,使用一次之后就会变成垃圾空间 -
Java简单类:
- 类中所有方法尽量不用System.out.语句,所有的输出交给调用处
- 应该提供有一个返回类完整信息的方法,如getInfo()。
数组的定义和使用
-
数组的访问通过索引完成,即:“数组名称[索引]”
-
动态初始化格式:
数据类型 数组名称 [ ] = new 数据类型 [ 长度 ]
静态初始化格式:
数据类型 数组名称 [ ] = new 数据类型 { 值,值,值...}
-
数组采用动态初始化开辟空间后,数组里面的每一个元素都是该数组对应数据类型的默认值
-
数组是有序、有限的集合
缺点:长度固定 -
如果要发生引用传递,等号右侧不要出现 “ [ ] ”
-
二维数组的输出,外部循环控制输出的行数,内部循环控制输出的列数
-
Java对数组的支持:
-
数组排序:
java.util.Arrays.sort();
public static void sort(int arr[]){ for(int x = 0; x < arr.length - 1 ; x ++){ for( int y = 0; y < arr.length - x - 1; y ++){ if (arr[y] > arr[y+1]){ int temp = arr[y]; arr[y] = arr[y+1]; arr[y+1] = temp; } } }
-
数组拷贝:将一个数组的部分内容替换掉另外一个数 组的部分内容
System.arraycopy(源数组名称,源数组开始点,目标数组名称,目标数组开始点,拷贝长度)
-
-
主方法相当于客户端调用,里面的代码应该越简单越好
-
数组反转:
- 思路1:创建等长数组
缺点:开辟了两块相同的堆内存空间。造成空间浪费 - 思路2:数组长度 / 2,在一个数组上完成
public static void reverse(int arr[]){ int center = arr.length / 2; int head = 0; int tail = arr.length - 1; for ( int x = 0; x < center; x++){ int temp = arr[head]; arr[head] = arr[tail]; arr[tail] = temp; head++; tail--; } }
- 思路1:创建等长数组
-
二维数组转置的前提:行列相等(x==y)
-
数组二分法查找(前提:数组排序):
采用方法递归完成public static int binarySearch(int arr[], int from. int to, int key){ if (from < to){ int mid = (from / 2)+ (to / 2); if ( arr[mid] == key){ return mid; }else if (key < arr[mid]){ return binarySearch(arr, from, mid-1, key); }else if (key >arr[mid]){ returnbinarySearch(arr, mid+1, to, key); } }else{ return -1; } }
-
对象数组
String类的基本特点
-
直接以赋值的形式声明:
String a = " ";
传统形式声明:String a = new String(" ");
两种实例化区别:
1⃣️直接赋值:如,str1 = "hello"; str2 = "hello"; str3 = "hello";
,并不会开辟新堆内存空间,原因在于String类的设计使用了一个共享设计模式,在JVM的底层实际上会自动维护一个对象池,如果采取直接赋值的模式进行String类对象的实例化操作,那么该实例化对象(字符串)将自动滴保存到这个对象池之中,如果下次继续有人使用了直接赋值的模式声明了String类的对象。如果此时对象池中有指定的内容,将直接进行引用;如果没有,则开辟新的字符串对象并保存在对象池之中,以供下次使用
2⃣️使用构造方法:标准做法,但有一块堆内存空间将会成为垃圾空间,此外该方法还会对字符串共享产生问题,需要手动处理进入对象池,如String str1 = new String("hello").intern();
-
字符串比较:
- “ == ”比较:本质上是地址数值比较,比较是否指向同一个堆内存
- “equals”比较:内容的比较,
str1.equals(str2);
-
字符串常量是String的匿名对象
System.out.println("hello".equals(str));
提示:在日后开发过程中,如果要判断用户输入的字符串是否等同于指定字符串,那么一定要将字符串写在前面,即"hello".equals(input)
-
字符串常量不可变更
所有语言对于字符串的底层实现都是字符数组(数组的最大缺陷就是长度固定)
!对字符串改变过多会形成大量垃圾空间 -
字符串和字符数组的相互转换,如
char data [ ] = str.toCharArray();
String str2 = new String(data);
-
字节与字符串:
(用户数据传输以及编码转换处理之中)
字节并不适合处理中文,只适用于处理二进制数据 -
字符串比较:
equalsIgnoreCase(String str);
不区分大小写比较
compareTo(String str);
比较大小关系,返回int(相等:返回0;小于:返回的内容小于0;大于:返回的内容大于0),即两者编码值的差 -
字符串查找:
contains()
、indexOf()
、lastIndexof()
、fromIndexOf()
、startsWith()
、endsWith()
… -
字符串替换:
replaceAll()
、replaceFirst()
…
字符串的替换操作与正则有关 -
字符串拆分:
split()
…
如果发现有些内容无法拆分开,就需要使用“ \ ”转义 -
字符串截取:
subString(int beginIndex)
、subString(int beginIndex, int endIndex)
…
截取的索引从0开始,且只能设置正整数 -
其他操作方法:
trim()
:去掉字符串中的左右空格,保留中间空格
toUpperCase()
:字符串转大写(不是字母的不转换,实际上就少了用户的判断)
intern()
:字符串的入池方法
concat()
:字符串连接,等同于“ + ”
length()
:取得字符串长度
isEmpty()
:判断字符串是否为空字符串,返回 true / false -
String类没有提供首字母大写的方法:
public static String initcap( String str){ if(str == null || "".equals(str)){ return str; } if(str.length() > 1){ return str.substring(0,1).toUpperCase() + str.substring(1); } return str.toUpperCase(); }
this关键字
-
调用本类属性:
参数与属性同名问题:为了明确标记处要使用的是属性还是方法的参数,建立属性前同一加上this. -
调用本类方法:
- 普通方法:this.方法名称(参数…)
- 构造方法:this(参数…)
(1) Java支持类构造方法的互相调用
(2) this()调用构造方法的语句必须放在构造方法的首行(不要产生递归构造调用?)
(3) 使用this调用构造方法的时候要留有出口
-
表示当前对象(相对概念)
在一个类中会产生若干个对象,程序类在分辨的时候不会记住具体有多少个对象产生了,它唯一可能知道的当前操作本类的对象是哪一个在整体的操作过程中,this定义没有变,只要有某一个对象调用了本类中的方法,那么这个this就表示当前执行的对象
引用传递分析
-
字符串常量一旦声明则不可改变,字符串的内容改变依靠的是地址的引用关系变更
public class TestDemo{ public static void main(String args[]){ String str = "hello"; fun(str); System.out.println(str); } public static void fun (String temp){ temp = "world"; } } //输出hello
-
传参
class Message{ private String note; public void setNote(String note){ this.note = note; } public String getNote(){ return this.note; } } public class TestDemo{ public static void main(String args[]){ Message msg = new Message(); msg.setNote("hello"); fun(msg); System.out.println(msg.getNote()); } public static void fun (Message temp){ temp.setNote("world"); } } //输出world;
-
对象比较需要根据对象所拥有的属性信息来进行完整比对,该功能应该是一个类本身所具备的功能,而不应该变为外部的操作。
class Person{ private int age; private String name; public Person(int age, String name){ this.name = name; this.age = age; } public boolean compare( Person per){ if ( per == this){ return true; } else if ( per == null){ return false; } else if ( this.name.equals( per.name) && this.age == per.age){ return true; } } } public class TestDemo{ public static void main(String args[]){ Person perA = new Person("Bob",20); Person perB = new Person("Bob",20); if (perA.compare(perB)){ System.out.println("两个对象相等!") } else { System.out.println("两个对象不等!") } } }
-
引用传递,可以更好的表现出现实世界的抽象【40 】
数据表与简单Java类
-
实际开发中的简单Java类设计原则
· 简单Java类的名称 = 实体表名称;
· 简单Java类的属性 = 实体表的字段;
· 简单Java类的一个对象 = 表的一行记录
· 对象数组 = 表的多行记录
· 外键关系 = 引用配置 -
举例(一对多):
一个部门有多个雇员,并且可以输出一个部门的完整信息(包括雇员信息);可以根据一个雇员找到雇员对应的领导信息和雇员所在部门信息
Step1 先按照给定的关系将所有的基础字段转化为类
Step2 进行关系设计,该数据表中对应有如下几个关系:
· 一个雇员属于一个部门:追加部门引用
· 一个雇员有一个领导:追加自身关联
· 一个部门有多个雇员:追加对雇员象数组描述
Step3 实现开发的需求
class Emp{
private int eno;
private String ename;
private String job;
private double salary;
private double comm;
private Emp mgr // 描述雇员领导
private Dept dept//描述雇员所在部门
public Emp(){
};
public Emp(int eno, String ename, String job, double salary, double comm){
this.eno = eno;
this.ename = ename;
this.job = job;
this.salary = salary;
this.comm = comm;
}
public void setMgr(Emp mgr){
this.mgr = mgr;
}
public Emp getMgr(){
return mgr;
}
public void setDept(Dept dept){
this.dept = dept;
}
public Dept getDept(){
return dept;
}
public String getInfo(){
return "【EMP】empo = " + this.eno + ",ename = "+ this.ename + ". job = " + this.job + ", salary = " + this.salary + ", comm = " + this.comm;
}
}
class Dept{
private int dno;
private String dname;
private String loc;
private Emp [] emps; //所有雇员
public Dept(){
};
public Dept(int dno, String dname, String loc){
this.dno = dno;
this.dname = dname;
this.loc = loc;
}
public void setEmps(Emp [] emps){
this.emps = emps;
}
public Emp [] getEmps(){
return this.emps;
}
public String getInfo(){
return "【DEPT】dno = " + this.dno + ",dname = "+ this.dname + ". loc = " + this.loc;
}
}
public class TestDemo{
public static void main(String args[]){
//第1:设置类对象间的关系
//(1):分别创建各自类的实例化对象
Dept dept = new Dept(10, "Accounting", "NY");
Emp ea = new Emp(0001, "Smith", "Clerk", 800.0, 0.0);
Emp eb = new Emp(0002, "Allen", "Manager". 2450.0, 0.0);
Emp ec = newEmp(0003, "King", "President", 5000.0, 0.0);
//(2):设置雇员领导的关系
ea.setMgr(eb);
eb.setMgr(ec);
//(3):设置雇员部门的关系
ea.setDept(dept);
eb.setDept(dept);
ec.setDept(dept);
//(4):设置部门雇员的关系
dept.setEmps(new Emps[] {
ea,eb,ec});
//第2:进行数据的取得
System.our.println(dept.getInfo());
for (int x = 0 ; x < dept.geyEmps().length; x ++){
System.out.println("\t|-"+dept.getEmps()[x].getInfo());
if ( dept.getEmps()[x].getMgr() != null){
System.out.println("\t\t|-"+dept.getEmps()[x].getMgr().getInfo());
}
}
System.out.println("===============");
}
}
- 举例(多对多):
——定义一个学生选择的操作表:
· 学生表 | 学生编号、姓名、年龄
· 课程表 | 课程编号、课程名、学分
· 学生-课程关系表 |学生编号、课程编号、成绩
——要求可以实现如下信息输出:
· 找到一门课程以及参加此课程的所有学生信息及其成绩
· 可以根据一个学生,找到他所参加的所有课程和每门课程的成绩
class Student{
private int stuid;
private String name;
private int age;
private StudentCourse studentCourses[];
public Student(){
}
public Student(int stuid, String name. int age){
this.stuid = stuid;
this.name = name;
this.age = age;
}
public void setStudentCourses(StudentCourse[] studentCourses){
this.studentCourses = studentCourses;
}
public StudentCourse[] getStudentCourses(){
return this.studentCourses;
}
public String getInfo