知识点1:类与对象
1. 二者的理解
* 类: 是对一类事物的描述,是抽象的、概念上的定义
* 对象:是实际存在的该类事物的每个个体,因而也称为实例(instance)
2. 类的设计
* 三、设计类,实际上就是设计类的内部成员
*
* 属性 = 成员变量 = field = 域 = 字段
* 方法 = 成员方法 = 函数 = 成员函数 = method
*
* 四、类的实例化 = 创建类的对象
*
- 代码体现
//设计类
class Phone{
//属性
String name;//品牌名
double price;//价格
//方法
public void call(){
System.out.println("打电话");
}
public void sendMessage(String message){
System.out.println("发出的信息为:" + message);
}
}
3. 类的实例化
public class OOPTest {
public static void main(String[] args) {
//Scanner的实例化:创建了一个Scanner类的对象
Scanner scann = new Scanner(System.in);
Scanner scann1 = new Scanner(System.in);
// scann.next();
String str1 = "hello";
String str2 = new String("abc");
//创建Phone的对象
Phone p1 = new Phone();
System.out.println("品牌名:" + p1.name + ", 价格为:" + p1.price);
//通过"对象.方法" 或 "对象.属性"的方式调用功能,完成设计
p1.name = "huawei p40 pro";
p1.price = 8000.0;
System.out.println("品牌名:" + p1.name + ", 价格为:" + p1.price);
p1.call();
p1.sendMessage("有内鬼,停止交易!");
System.out.println("##########################");
Phone p2 = new Phone();
p2.name = "xiaomi 10";
Phone p3 = p1;
p3.price = 7000.0;
System.out.println(p1.price);
}
}
//设计类
class Phone{
//属性
String name;//品牌名
double price;//价格
//方法
public void call(){
System.out.println("打电话");
}
public void sendMessage(String message){
System.out.println("发出的信息为:" + message);
}
}
- 总结
五、面向对象编程思想落地的实现:
步骤1:创建类,设计类的成员:属性、方法
步骤2:创建类的对象 ( 或 类的实例化)
步骤3:通过"对象.方法" 或 "对象.属性"的方式调用功能,完成设计
4. 对象的内存解析
六、对象的内存解析
* 对象名保存在栈空间中。对象实体保存在堆空间中,对象的属性也保存在堆空间中
*
* 七、
* 1)创建类的多个对象,每个对象就拥有一套类的属性。当修改其中一个对象的某个属性a时,不会影响其他对象的属性a的值。
* 比如:下例中的p1,p2。
* 2)如果将一个对象的引用赋给另一个对象的引用。则表示两个引用指向了堆空间的同一个对象实体。
* 如果通过其中引用修改其对象的属性值的话,则会影响到另外的引用对此属性的调用。
* 比如:下例中的p1,p3
知识点2:属性 vs 局部变量
- 说明
/**
*
* 测试类中属性的声明
*
* 1. 变量的分类
* 1)按数据类型来分:基本数据类型 (8种) vs 引用数据类型(数组、类、接口)
* 2)按在类中声明的位置: 成员变量 vs 局部变量
* 成员变量:直接声明在类中。
* 局部变量:方法内、构造器内、代码块内、方法的形参、构造器的形参等
*
*
* 2. 对比 成员变量 vs 局部变量
*
* 相同点:
* > 都是变量,定义的格式相同:数据类型 变量名 = 变量值
* > 先声明,后使用
* > 变量都有其作用域。超出作用域就失效
*
* 不同点:
* ① 关于权限修饰符的使用(了解)
* 成员变量声明前可以使用不同的权限修饰符进行修饰。比如:private \ 缺省 \ protected \ public
* 局部变量不能使用权限修饰符进行修饰。
*
* ② 关于变量赋值的说明
* 成员变量可以显式赋值,也可以使用默认初始化值
* 局部变量必须在调用之前显式赋值。因为其没有默认初始化值
*
* 对于成员变量默认初始化值的情况:
* 整型,默认值为:0
* 浮点型:默认值为:0.0
* char型:默认值为:0 或 '\u0000'
* boolean型:默认值为:false
* 引用数据类型:默认值为null
*
* ③ 在类中声明的位置不同
* 成员变量:直接声明在类内部
* 局部变量:声明在方法内、构造器内、代码块内、方法的形参、构造器的形参等
* ④ 在内存结构中的位置不同
* 成员变量:声明在堆空间中
* 局部变量:声明在栈空间中
*/
- 代码演示
public class PersonTest {//测试类
public static void main(String[] args) {
Person p1 = new Person();
System.out.println(p1.name);
System.out.println(p1.age);
System.out.println(p1.gender);
p1.eat("鱼香肉丝");
p1.name = "李金鑫";
}
}
class Person{
//属性(或成员变量)
String name;
int age;
boolean gender;//true:女性 false:男性
//方法
public void eat(String food){//food:形参。形参属于局部变量
System.out.println("我喜欢吃:" + food);
}
public void sleep(){
int minHour = 6; //属于局部变量
int maxHour = 10;//属于局部变量
System.out.println("每天睡眠建议不要少于" + minHour + ",但是也不要睡的过多。建议不要超过" + maxHour + "小时");
}
}
知识点3: 方法的声明和使用
- 说明
/**
*
* 测试类中方法的声明
*
* 1. 方法声明的整体格式:
* 权限修饰符 返回值类型 方法名(参数类型1 参数名1,参数类型2 参数名2,...){
* //方法体
* }
*
* 说明:
* ① 权限修饰符:可以使用4种不同的权限修饰来修饰方法。比如:private \ 缺省 \ protected \ public
* 暂时大家在声明方法时,可以默认都声明为:public
* ② 关于返回值类型分为两种情况:① 没有返回值类型 ② 有具体的返回值类型
* > 没有返回值类型,使用void表示。比如:Arrays的sort()
* > 有具体的返回值类型。可以是任意的基本数据类型或引用数据类型。
* 比如:Arrays.binarySearch(int[] arr,int target),Arrays.equals(int[] arr,int[] arr1)
* Math的random() 和 sqrt(double value)
* 有具体返回值类型的方法中,一定会使用“return + 变量/常量”的方式,返回满足具体类型的数据。
* ③ 方法名:属于标识符,命名时满足标识符的命名规则和规范;“见名知意”
* ④ 形参列表:可以在声明方法时,在()内存入方法体在执行过程中,必要的一些数据。
* ⑤ 方法体:当我们调用方法时,方法执行的结构。
*
* 此外,方法还可以使用一些关键字修饰:static \ abstract \ final 等,后面再讲
* 方法还可以在形参列表之后声明抛出的异常类型。在异常处理章节讲。
*
* 2. 重点需要大家体会:声明方法时,是否需要返回值类型,是否需要形参列表。
* ① 看题目要求。
* ② 具体问题具体分析。
*
* 3. return的使用
* 作用1:在方法中一旦执行此关键字,就结束方法的执行。
* 作用2:在有返回值类型的方法中,使用“return + 变量/常量”,返回需要的数据类型对应的数据。
*
* 4. 我们可以在类的方法中,调用本类中的属性或方法(暂时是调用其他方法)
*/
- 代码演示
public class UserTest {
public static void main(String[] args) {
int[] arr = new int[]{45,63,5,5,34,57};
Arrays.sort(arr);
System.out.println(Arrays.toString(arr));
User u1 = new User();
u1.eat("水煮鱼");
int years = u1.studyYears();
System.out.println(years);//12
System.out.println("############");
u1.printNumber();
u1.info();
}
}
class User{
//属性
String name;
int age = 1;
//方法的声明
public void eat(String food){//food:形参。形参属于局部变量
System.out.println("我喜欢吃:" + food);
}
public void sleep(){
int minHour = 6; //属于局部变量
int maxHour = 10;//属于局部变量
System.out.println("每天睡眠建议不要少于" + minHour + ",但是也不要睡的过多。建议不要超过" + maxHour + "小时");
return;
}
public int studyYears(){
byte years = 12;
return years;
}
public void info(){
System.out.println("name = " +name + ", age = " + age);
eat("宫保鸡丁");
// info();
}
public void printNumber(){
for(int i = 1;i <= 100;i++){
if(i == 10){
return;
}
System.out.println(i);
}
System.out.println("hello");
}
}
知识点4:方法的重载
package com.atguigu.java1;
/**
*
* 测试方法的重载(overload)
*
* 1.理解:同一个类中,相同方法名,不同参数列表的多个方法之间,彼此构成方法的重载
* 总结:“两同一不同”: 相同类中、相同方法名
* 参数列表不同:参数个数不同,参数类型不同
*
* 2. 方法的重载与权限修饰符、返回值类型、形参名都没有关系
*
* 3. 如何确定调用一个类的中哪个方法?
* 第1步:通过方法名
* 第2步:通过形参列表的个数和类型
*
*/
public class OverLoadTest {
public static void main(String[] args) {
OverLoadTest test = new OverLoadTest();
byte b1 = 10;
int i = 20;
test.func(b1,i);
long l = 10L;
// test.func(b1,l);//找不到此方法
}
//如下的方法构成重载
public void sum(int i,int j){
}
public void sum(int i,int j,int k){
}
public void sum(byte b1 ,byte b2){
}
//如下的方法构成重载
public void func(byte b1,int i){
System.out.println(b1 + i);
}
public void func(int i,byte b1){
}
// public void func(byte b2,int i1){
// System.out.println(b2 - i1);
// }
// public int func(byte b1,int i){
//
// return b1 + i;
// }
}
知识点5:匿名对象
/**
*
* 测试匿名对象
*/
public class PhoneTest1 {
public static void main(String[] args) {
Phone p1 = new Phone();
p1.name = "huawei p40";
p1.price = 6000;
p1.call();
//#########################
//如果对某个对象的使用,只调用一次,则可以考虑创建匿名对象
new Phone().call();
new Phone().name = "xiao mi 10";
//#########################
Customer cust = new Customer();
cust.show(p1);
cust.show(new Phone());//
}
}
class Customer{
public void show(Phone phone){
phone.call();
}
}
典型题目:对象数组
package com.atguigu.exer;
/**
* <p>
* 对象数组题目:
* 定义类Student,包含三个属性:学号number(int),年级state(int),成绩score(int)。
* 创建20个学生对象,学号为1到20,年级和成绩都由随机数确定。
* 问题一:打印出3年级(state值为3)的学生信息。
* 问题二:使用冒泡排序按学生成绩排序,并遍历所有学生信息
* <p>
* 提示:
* 1) 生成随机数:Math.random(),返回值类型double;
* 2) 四舍五入取整:Math.round(double d),返回值类型long。
*/
public class StudentTest {
public static void main(String[] args) {
//1. 创建Student[]的数组,长度为20 ---> 动态初始化
Student[] stus = new Student[20];
//2.通过循环,给每个数组元素赋值(即:创建对象)
for (int i = 0; i < stus.length; i++) {
stus[i] = new Student();
//3. 给数组中的每个Student对象的属性赋值
stus[i].number = i + 1;
stus[i].state = (int) (Math.random() * 6 + 1); //[1,6]
stus[i].score = (int) (Math.random() * (100 - 0 + 1));//[0,100]
}
//打印学生的基本信息
for (int i = 0; i < stus.length; i++) {
// System.out.println("number : " + stus[i].number +
// ", state : " + stus[i].state + ", score : " + stus[i].score);
// stus[i].info();
Student s = stus[i];
s.info();
}
//问题一:打印出3年级(state值为3)的学生信息。
// for(int i = 0;i < stus.length;i++){
// if(stus[i].state == 3){
// stus[i].info();
// }
// }
//问题二:使用冒泡排序按学生成绩排序,并遍历所有学生信息
for (int i = 0; i < stus.length - 1; i++) {
for (int j = 0; j < stus.length - 1 - i; j++) {
if (stus[j].score > stus[j + 1].score) {
//错误的:
// int tempScore = stus[j].score;
// stus[j].score = stus[j + 1].score;
// stus[j + 1].score = tempScore;
//正确的:
Student tempStu = stus[j];
stus[j] = stus[j + 1];
stus[j + 1] = tempStu;
}
}
}
System.out.println("排序后:");
//打印学生的基本信息
for (int i = 0; i < stus.length; i++) {
Student s = stus[i];
s.info();
}
}
}
class Student {//学生类
int number;//学号
int state;//年级
int score;//成绩
public void info() {
System.out.println("number : " + number +
", state : " + state + ", score : " + score);
}
}