1)类是抽象的,概念的,代表一类事物,比如人类、猫类,是数据类型。
2)对象是具体的,实际的,代表一个具体事物,即实例。
3)类是对象的模板,对象是类的一个个实体,对应一个实例,
1.3 对象在内存中存在的形式 1.4 属性/成员变量/字段 1.4.1 基本介绍1)从概念或叫法上看:成员变量 = 属性 = field(字段)
2)属性是类的一个组成部分,一般是基本数据类型,也可以是引用数据类型(对象、数组)。
1.4.2 注意事项和细节说明1)属性的定义语法同变量,示例:访问修饰符 属性类型 属性名;
四种访问修饰符:public、 protected、 默认 、private
2)属性的定义类型可以是任意类型,包括基本类型或引用类型。
3)属性如果不赋值,有默认值,规则和数组一致。
int 0、short 0、byte 0、long 0、float 0、double 0、char u0000、boolean false、String null
1.5 如何创建对象1)先声明后创建
Cat cat; cat = new Cat();
2)直接创建
Cat cat = new Cat();1.6 如何访问属性 1.6.1 基本语法
对象名.属性名
cat.name; cat.age; cat.color;1.6.2 类与对象的内存分配机制
看下面一段代码,分析p2.age是多少?并画出内存图
Person p1 = new Person(); //第1步 p1.age = 10; //第2步 p1.name = "小明"; //第3步 Person p2 = p1; //第4步 System.out.println(p2.age); //p2.age = 10;1.7 类与对象的内存分配机制 1.7.1 java内存结构分析
1)栈:一般存放基本数据类型(局部变量)
2)堆:存放对象(Cat cat、数组等)
3)方法区:常量池(常量、比如字符串),类加载信息
1.7.2 java创建对象的简单流程分析Person p = new Person(); p.name = "jack"; p.age = 10;
1)先加载Person类信息(属性信息和方法信息,只会加载一次);
2)在堆中分配空间,进行默认初始化
3)比地址赋给p,p就指向对象
4)进行指定初始化,比如:
p.name = "jack"; p.age = 10;
看题分析内存布局图
Person a = new Person(); a.age = 10; a.name = "小明"; Person b; b = a; System.out.println(b.name); //小明 b.age = 200; b = null; Syetem.out.println(a.age); //200 System.out.println(b.age); //异常2 成员方法 2.1 基本介绍
在某些情况下,我们要需要定义成员方法(简称方法)。比如人类:除一些属性外(年龄,姓名),还有一些行为(说话、跑步、学习等)。这时就要用成员方法才能完成。
2.2 成员方法快速入门1)添加speak成员方法,输入"你是一个好人"
class Person{
public void speak(){
System.out.println("你是一个好人");
}
}
2)添加cal01成员方法,可以计算从1+…+1000的结果
class Person{
public void cal01(){
int sum = 0;
for(int i = 1; i <= 1000; i++){
sum += i;
}
System.out.println("sum = " + sum);
}
}
3)添加cal02成员方法,该方法可以接收一个数n,计算从1+…+n的结果
public void cal01(int n){
int sum = 0;
for(int i = 1; i <= n; i++){
sum += i;
}
System.out.pritnln("sum = " + sum);
}
4)添加getSum成员方法,可以计算两个数的和
public int getSum(int n, int m){
int sum = n + m;
return sum;
}
2.3 方法调用机制原理
画出下面代码的内存执行图
public class Object01{
public static void main(String[] args){
Person p = new Person();
int res = p.getSum(10, 20);
System.out.println("res = " + res);
}
}
class Person{
public int getSum(int n, int m){
int res = n + m;
return res; }
}
2.4 成员方法的好处
1)提高代码的复用性
2)可以将实现的细节封装起来,然后供其他用户调用即可
2.5 成员方法的定义访问控制修饰符 返回数据类型 方法名 (形参列表){
//方法体
语句;
return 返回值;
}
1)形参列表:表示成员方法输入的数据,如:cal(int n),getSum(int n, int m)
2)返回数据类型:表示成员方法输出,void表示没有返回值。
3)方法主体:表示为了实现某一功能的代码块。
4)return语句不是必须的。
2.6 注意事项和使用细节 2.6.1 访问修饰符访问修饰符的作用是控制方法使用的范围,如果不写则为默认。
2.6.2 返回数据类型1)一个方法最多有一个返回值,如果要多个返回结果,可以使用数组
2)返回类型可以为任意类型,包含基本类型和引用类型
3)如果方法要求有返回数据类型,则方法体最后的执行语句必须是 return 值;而且要求返回值类型必须和return值类型一致或兼容。
4)如果返回数据类型为void,则方法体中可以不写 return 语句或只写 return;。
2.6.3 方法名遵循驼峰命名法,最好是见名知意,表达出该功能的意思即可。
2.6.4 形参列表1)一个方法可以有0个参数,也可以有多个参数,中间用逗号隔开。
2)参数类型可以为任意类型,包含基本类型和引用类型。
3)调用带参数的方法时,一定对应着参数列表传入相同类型或兼容类型的参数。
4)方法定义时的参数称为形式参数,简称形参;方法调用时传入的参数称为实际参数,简称实参,实参和形参的类型必须要一致或兼容、个数、顺序必须一致。
2.6.5 方法体里面写完成功能的具体语句,可以为输入、输出、变量、运算、分支、循环、方法调用,但里面不能再定义方法。即:方法不能嵌套定义。
2.6.6 方法调用细节1)同一个类中方法可以直接调用
2)跨类中的方法需要通过对象名调用。比如 对象名.方法名
3)跨类的方法调用和方法的访问修饰符有关。
public class MethodDetail02 {
//编写一个 main 方法
public static void main(String[] args) {
A a = new A();
a.sayOk();
a.m1();
}
}
class A {
//同一个类中的方法调用:直接调用即可
public void print(int n) {
System.out.println("print()方法被调用 n=" + n);
}
public void sayOk() { //sayOk 调用 print(直接调用即可)
print(10);
System.out.println("继续执行 sayOK()~~~");
}
//跨类中的方法 A 类调用 B 类方法:需要通过对象名调用
public void m1() {
//创建 B 对象, 然后在调用方法即可
System.out.println("m1() 方法被调用");
B b = new B();
b.hi();
System.out.println("m1() 继续执行:)");
}
}
class B {
public void hi() {
System.out.println("B 类中的 hi()被执行");
}
}
2.7 练习
1)编写类AA,有一个方法:判断一个数是奇数odd还是偶数,返回boolean
import java.util.Scanner;
public class Test2{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
System.out.println("请输入一个整数:");
int n = sc.nextInt();
AA a = new AA();
if(a.isOdd(n)){
System.out.println("输入的数为奇数");
} else {
System.out.println("输入的数为偶数");
}
}
}
class AA{
public boolean isOdd(int n){
if(n % 2 != 0){
return true;
} else {
return false;
}
}
}
2)根据行、列、字符打印对应行数和列数的字符
import java.util.Scanner;
public class Test2{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
System.out.println("请输入要打印的行:");
int n = sc.nextInt();
System.out.println("请输入要打印的列:");
int m = sc.nextInt();
System.out.println("请输入要打印的字符:");
char c = sc.next().charAt(0);
AA a = new AA();
System.out.println("=====================");
a.print(n, m, c);
}
}
class AA{
public void print(int n, int m, char c){
for(int i = 0; i < n; i++){
for(int j = 0; j < m; j++){
System.out.print(c);
}
System.out.println(); //换行
}
}
}
3 成员传参机制
3.1 基本数据类型的传参机制
看下面代码,分析执行结果
public class MethodParameter01 {
//编写一个 main 方法
public static void main(String[] args) {
int a = 10;
int b = 20;
//创建 AA 对象 名字 obj
AA obj = new AA();
obj.swap(a, b); //调用 swap
System.out.println("main 方法 a=" + a + " b="
+ b);//a=10 b=20
}
}
class AA {
public void swap(int a,int b){
System.out.println("na 和 b 交换前的值na=" + a
+ "tb=" + b);//a=10 b=20
//完成了 a 和 b 的交换
int tmp = a;
a = b;
b = tmp;
System.out.println("na 和 b 交换后的值na=" + a
+ "tb=" + b);//a=20 b=10
}
}
3.2 引用数据类型的传参机制
分析下面案例的执行结果
1)B 类中编写一个方法 test100,可以接收一个数组,在方法中修改该数组,看看原来的数组是否变化?
public class Test2{
public static void main(String[] args){
int[] arr = {1, 2, 3};
System.out.println("最初的arr数组");
for(int i = 0; i < arr.length; i++){
System.out.print(arr[i] + " ");// 1 2 3
}
System.out.println("n=================");
B b = new B();
b.test100(arr);
System.out.println("n=================");
System.out.println("main打印arr数组");
for(int i = 0; i < arr.length; i++){
System.out.print(arr[i] + " ");// 3 2 3
}
}
}
class B{
public void test100(int[] arr){
arr[0] = 3;
System.out.println("B类打印arr数组");
for(int i = 0; i < arr.length; i++){
System.out.print(arr[i] + " ");// 3 2 3
}
}
}
2)B 类中编写一个方法 test200,可以接收一个 Person(age,sal)对象,在方法中修改该对象属性,看看原来的对象是否变化?会变化
public class Test2{
public static void main(String[] args){
Person p = new Person();
p.age = 20;
p.sal = 8000;
System.out.println("p.age = " + p.age + " p.sal = "
+ p.sal);//p.age = 20; p.sal = 8000.0
B b = new B();
b.test200(p);
System.out.println("p.age = " + p.age + " p.sal = "
+ p.sal);//p.age = 1000; p.sal = 8000.0
}
}
class B{
public void test200(Person p){
p.age = 1000;
}
}
class Person{
int age;
double sal;
}
3.3 成员方法返回类型是引用类型实例
1)编写类 MyTools 类,编写一个方法可以打印二维数组的数据。
public class Test2{
public static void main(String[] args){
int[][] arr = {{1}, {2, 2}, {3, 3, 3}};
MyTool myTool = new MyTool();
myTool.print(arr);
}
}
class MyTool{
public void print(int[][] arr){
for(int i = 0; i < arr.length; i++){
for(int j = 0; j < arr[i].length; j++){
System.out.print(arr[i][j] + " ");
}
System.out.println();
}
}
}
2)编写一个方法 copyPerson,可以复制一个 Person 对象,返回复制的对象。克隆对象, 注意要求得到新对象和原来的 对象是两个独立的对象,只是他们的属性相同
public class Test2{
public static void main(String[] args){
Person p = new Person();
p.age = 20;
p.name = "张三";
System.out.println("p.age = " + p.age
+ " p.name = " + p.name);
MyTool myTool = new MyTool();
Person p1 =myTool.copyPerson(p);
System.out.println("p1.age = " + p1.age
+ " p1.name = " + p1.name);
System.out.println(p == p1);
}
}
class MyTool{
public Person copyPerson(Person p){
Person p1 = new Person();
p1.age = p.age;
p1.name = p.name;
return p1;
}
}
class Person{
int age;
String name;
}
4 方法递归调用
4.1 基本介绍
简单来说:递归就是方法自己调用自己,每次调用时传入不同的变量,递归有助于编程者解决复杂问题,同时可以让代码变得简洁
4.2 递归举例1)打印问题
public class Recursion01 {
//编写一个 main 方法
public static void main(String[] args) {
T t1 = new T();
t1.test(4);//输出什么? n=2 n=3 n=4
}
}
class T {
//分析
public void test(int n) {
if (n > 2) {
test(n - 1);
}
System.out.println("n=" + n);
}
}
2)阶乘问题
public class Recursion01 {
//编写一个 main 方法
public static void main(String[] args) {
T t1 = new T();
int res = t1.factorial(5);
System.out.println("5 的阶乘 res =" + res);
}
}
public T{
public int factorial(int n) {
if (n == 1) {
return 1;
} else {
return factorial(n - 1) * n;
}
}
}
4.3 递归重要原则
1)执行一个方法时,就创建一个新的受保护的独立空间(栈空间)。
2)方法的局部变量是独立的,不会相互影响,比如n变量。
3)如果方法中使用的是引用类型变量,就会共享该引用类型的数据。
4)递归必须向退出递归的条件逼近,否则就会出现无限递归。
5)当一个方法执行完毕,或者遇到return,就会返回,遵守谁调用,就将结果返回给谁,同时当方法执行完毕或者返回时,该方法也就执行完毕。
4.4 练习1)使用递归的方式求出斐波那契数1,1,2,3,5,8,13…给你一个整数,求出它的值。
import java.util.Scanner;
public class Test2{
public static void main(String[] args){
Scanner sc =new Scanner(System.in);
MyTool myTool = new MyTool();
System.out.println("请输入一个数:");
int n = sc.nextInt();
int f = myTool.fibo(n);
System.out.println("第" + n + "个数对应的是:" + f);
}
}
class MyTool{
public int fibo(int n){
if(n == 1 ||n == 2){
return 1;
} else {
return fibo(n-1) + fibo(n-2);
}
}
}
2)猴子吃桃问题:有一堆桃子,猴子第一天吃了其中的一半,并再多吃一个!以后每天猴子都吃其中的一半,然后再多吃一个。当第十天时,想再吃时(即还没吃),发现只有一个桃子。问:最初有多少桃子?
import java.util.Scanner;
public class Test2{
public static void main(String[] args){
Scanner sc =new Scanner(System.in);
MyTool myTool = new MyTool();
System.out.println("请输入天数:");
int n = sc.nextInt();
int f = myTool.peach(n);
System.out.println("第" + n + "天有:" + f + "个桃子");
}
}
class MyTool{
public int peach(int n){
if(n == 10){
return 1;
} else {
return (peach(n + 1) + 1) * 2;
}
}
}
5 方法重载
5.1 基本介绍
java中允许同一个类,多个同名方法存在,但要求形参列表不一致。
5.2 重载的好处1)减少了起名的方法
2)减轻了记名的麻烦
5.3 快速入门calculate(int n1, int n2); calculate(int n1, double n2); calculate(double n1, int n2); calculate(double n1, double n2);5.4 注意事项和使用细节
1)方法名:必须相同
2)形参列表:必须不同(形参类型或个数或顺序,至少有一样不同,参数名无要求)
3)返回类型:无要求
6 可变参数 6.1 基本介绍Java允许将同一个类中多个同名同功能但参数不同的方法封装成一个方法。
基本语法
访问修饰符 返回类型 方法名(数据类型... 形参名){
}
6.2 快速入门
public class OverLoadExercise {
public static void main(String[] args) {
Methods methods = new Methods();
System.out.println("methods.sum(1, 4, 5)的和为:" + methods.sum(1, 4, 5));
System.out.println("methods.sum(2, 7)的和为:" + methods.sum(2, 7));
System.out.println("methods.sum(5, 6, 7, 8)的和为:" + methods.sum(5, 6, 7, 8));
}
}
class Methods{
public int sum(int... num){
int sum = 0;
for (int i = 0; i < num.length; i++) {
sum += num[i];
}
return sum;
}
}
6.3 注意事项和使用细节
1)可变参数的实参可以是0个或任意多个。
2)可变参数的实参可以是数组。
3)可变参数的本质就是数组。
4)可变参数可以和普通类型的参数一起放入形参列表,但可变参数必须放在最后
5)一个形参列表只能出现一个可变参数。
7 作用域 7.1 基本使用1)在Java编程中,主要的变量就是属性(成员变量)和局部变量。
2)我们说的局部变量一般是指在成员方法中的变量。
3)Java中的作用域分类:
全局变量:也就是属性,作用域是整个类体
局部变量:也就是除了属性之外其他变量,作用域为定义它的代码块中。
4)全局变量(属性)可以不赋值直接使用,因为有默认值,局部变量必须赋值后才能使用,因为没有默认值。
7.2 注意事项和使用细节1)属性和局部变量可以重名,访问时遵循就近原则。
2)在同一作用域中,比如在同一个成员方法中,两个局部变量不能重名。
3)属性声明周期长,伴随着对象的创建而创建,伴随着对象的销毁而销毁。局部变量,生命周期短,伴随着它的代码块的执行而创建,伴随着代码块的结束而销毁。即再一次方法调用过程中。
4)作用于范围不同:
全局变量/属性:可以在本类使用,或其他类使用(通过对象调用)
局部变量:只能作用在本类对应的方法中。
5)全局变量可以加修饰符,局部变量不可以。
8 构造器/构造方法 8.1 基本介绍构造器又叫构造方法,是类的一种特殊用法,它的主要功能是完成新对象的初始化。有以下特点:
1)方法名和类型相同
2)没有返回值
3)在创建对象时,系统会自动调用该类的构造器完成对象的初始化
8.2 基本语法[访问修饰符] 方法名 (形参列表){
方法体;
}
说明:
1)构造器的修饰符可以默认,也可以是public protected private
2)构造方法没有返回值
3)方法名和类名必须一样
4)参数列表和成员方法一样的规则
5)构造器的调用由系统完成
8.3 注意事项和使用细节1)一个类可以有多个不同的构造器,即构造器重载
2)构造器名和类名要相同
3)构造器没有返回值
4)构造器是完成对象的初始化,并不是创建对象
5)在创建对象时,系统自动调用该类的构造器
6)如果程序员没有定义构造器,系统会自动生成一个默认无参构造器
7)一旦定义了自己的构造器,默认的无参构造器也就被覆盖,不能再使用,除非再定义一个无参构造器。
9 this关键字的注意对象和使用细节1)this关键字可以用来访问本类属性、方法、构造器
2)this用于区分当前类的属性和局部变量
3)访问成员方法的语法:this.方法名(参数列表);
4)访问构造器语法:this(参数列表);注意只能在构造器中使用(即只能在构造器中访问另外一个构造器,必须放在第一条语句)
5)this类不能定义在外部使用,只能在类定义的方法中使用。



