1、面向对象的简单说明
1 /* 2 事物: 3 属性 事物的信息描述 4 行为 事物的功能 5 6 类: 7 成员变量 事物的属性 8 成员方法 事物的行为 9 10 定义一个类,其实就是定义该类的成员变量和成员方法。11 12 手机事物:13 属性:品牌,价格,颜色...14 行为:打电话,发短信,玩游戏...15 16 手机类:17 成员变量:品牌,价格,颜色18 成员方法:打电话,发短信,玩游戏19 20 成员变量:和以前变量的定义是一样的格式,但是位置不同,在类中方法外。21 成员方法:和以前的方法定义是一样的格式,但是今天把static先去掉。22 */23 class Phone {24 //品牌25 String brand;26 //价格27 int price;28 //颜色29 String color;30 31 //打电话的方法32 public void call(String name) {33 System.out.println("给"+name+"打电话");34 }35 36 //发短信的方法37 public void sendMessage() {38 System.out.println("群发短信");39 }40 41 //玩游戏的方法42 public void playGame() {43 System.out.println("玩游戏");44 }45 }
一个对象的内存分布:
两个对象的内存分部:
三个对象的内存分部:
2、成员变量和局部变量的区别
1 /* 2 成员变量和局部变量的区别? 3 A:在类中的位置不同 4 成员变量:在类中方法外 5 局部变量:在方法定义中或者方法声明上 6 B:在内存中的位置不同 7 成员变量:在堆内存 8 局部变量:在栈内存 9 C:生命周期不同10 成员变量:随着对象的创建而存在,随着对象的消失而消失11 局部变量:随着方法的调用而存在,随着方法的调用完毕而消失12 D:初始化值不同13 成员变量:有默认初始化值14 局部变量:没有默认初始化值,必须定义,赋值,然后才能使用。15 16 注意事项:17 局部变量名称可以和成员变量名称一样,在方法中使用的时候,采用的是就近原则。18 */19 class Varialbe {20 //成员变量21 //int num = 10;22 int num; //023 24 public void show() {25 //int num2 = 20; //局部变量26 //可能尚未初始化变量num227 //int num2; //没有默认值28 int num2 = 20;29 System.out.println(num2);30 31 //int num = 100;32 System.out.println(num);33 }34 }35 36 37 class VariableDemo {38 public static void main(String[] args) {39 Varialbe v = new Varialbe();40 41 System.out.println(v.num); //访问成员变量42 43 v.show(); 44 45 }46 }
3、形式参数是类名
1 /* 2 形式参数的问题: 3 基本类型:形式参数的改变不影响实际参数 4 引用类型:形式参数的改变直接影响实际参数 5 */ 6 //形式参数是基本类型 7 class Demo { 8 public int sum(int a,int b) { 9 return a + b;10 }11 }12 13 //形式参数是引用类型14 class Student {15 public void show() {16 System.out.println("我爱学习");17 }18 }19 20 class StudentDemo {21 //当一个方法的形式参数是一个类类型(引用类型),这里其实需要的是该类的对象。22 public void method(Student s) { //调用的时候,把main方法中的s的地址传递到了这里 Student s = new Student();23 s.show();24 }25 }26 27 class ArgsTest {28 public static void main(String[] args) {29 //形式参数是基本类型的调用30 Demo d = new Demo();31 int result = d.sum(10,20);32 System.out.println("result:"+result);33 System.out.println("--------------");34 35 //形式参数是引用类型的调用36 //需求:我要调用StudentDemo类中的method()方法37 StudentDemo sd = new StudentDemo();38 //创建学生对象39 Student s = new Student();40 sd.method(s); //把s的地址给到了这里41 }42 }
4、匿名对象
1 /* 2 匿名对象:就是没有名字的对象。 3 4 匿名对象的应用场景: 5 A:调用方法,仅仅只调用一次的时候。 6 注意:调用多次的时候,不适合。 7 那么,这种匿名调用有什么好处吗? 8 有,匿名对象调用完毕就是垃圾。可以被垃圾回收器回收。 9 B:匿名对象可以作为实际参数传递10 */11 class Student {12 public void show() {13 System.out.println("我爱学习");14 }15 }16 17 class StudentDemo {18 public void method(Student s) {19 s.show();20 }21 }22 23 class NoNameDemo {24 public static void main(String[] args) {25 //带名字的调用26 Student s = new Student();27 s.show();28 s.show();29 System.out.println("--------------");30 31 //匿名对象32 //new Student();33 //匿名对象调用方法34 new Student().show();35 new Student().show(); //这里其实是重新创建了一个新的对象36 System.out.println("--------------");37 38 39 //匿名对象作为实际参数传递40 StudentDemo sd = new StudentDemo();41 //Student ss = new Student();42 //sd.method(ss); //这里的s是一个实际参数43 //匿名对象44 sd.method(new Student());45 46 //在来一个47 new StudentDemo().method(new Student());48 }49 }
5、封装和private关键字
1 /* 2 private: 3 是一个权限修饰符 4 可以修饰成员变量和成员方法 5 被其修饰的成员只能在本类中被访问 6 */ 7 class Demo { 8 //int num = 10; 9 //用private修饰10 private int num = 10;11 12 public void show() {13 System.out.println(num);14 }15 16 private void method() {17 System.out.println("method");18 }19 20 public void function() {21 method();22 }23 }24 25 class PrivateDemo {26 public static void main(String[] args) {27 Demo d = new Demo();28 //不能方法私有的成员变量29 //System.out.println(d.num);30 d.show();31 //不能访问私有的成员方法32 //d.method();33 d.function();34 }35 }
1 /* 2 定义一个学生类: 3 成员变量:name,age 4 成员方法:show()方法 5 6 我们在使用这个案例的过程中,发现了一个问题: 7 通过对象去给成员变量赋值,可以赋值一些非法的数据。 8 这是不合理的。 9 应该是这个样子的:在赋值之前,先对数据进行判断。10 判断到底在哪里做比较合适呢?11 StudentDemo类是一个测试类,测试类一般只创建对象,调用方法。 12 所以,这个判断应该定义在Student类中。13 而我们在成员变量的位置可不可以进行数据判断呢?14 是不可以的,因为做数据校验,必须要依靠一些逻辑语句。15 逻辑语句是应该定义在方法中的,所以,我们最终决定在Student类中提供一个方法16 来对数据进行校验。17 18 按照我们前面的分析,我们给出了一个方法进行校验。19 但是呢,它偏偏不调用方法来赋值,还是直接赋值了,20 这样我们的方法就没有起到作用。21 我就应该要求你必须使用我的方法,而不能直接调用成员变量赋值。22 怎么去强制要求不能直接使用成员变量呢?23 针对这种情况,Java就提供了一个关键字 private24 25 private:私有的。可以修饰成员变量和成员方法。26 注意:被private修饰的成员只能在本类中访问。27 28 其实我讲到现在讲解的是一个封装的思想。29 封装:是指隐藏对象的属性和实现细节,仅对外提供公共访问方式。30 */31 class Student {32 //姓名33 String name;34 //年龄35 private int age;36 37 //写一个方法对数据进行校验38 /*39 返回值类型:void40 参数列表:int a41 */42 public void setAge(int a) {43 if(a < 0 || age > 120) {44 System.out.println("你给的年龄有问题");45 }else {46 age = a;47 }48 }49 50 51 //show()方法,显示所有成员变量值52 public void show() {53 System.out.println("姓名:"+name);54 System.out.println("年龄:"+age);55 }56 }57 58 class StudentDemo {59 public static void main(String[] args) {60 //创建学生对象61 Student s = new Student();62 s.show();63 System.out.println("--------------");64 65 //给成员变量赋值66 s.name = "林青霞";67 //s.age = 27;68 s.setAge(27);69 s.show();70 System.out.println("--------------");71 72 //给age赋值73 //s.age = -27; //这个数据是不合理的74 //通过方法给值75 s.setAge(-27);76 s.show();77 System.out.println("--------------");78 }79 }
1 /* 2 封装和private的应用: 3 A:把成员变量用private修饰 4 B:提高对应的getXxx()和setXxx()方法 5 */ 6 //定义学生类 7 class Student { 8 //姓名 9 private String name;10 //年龄11 private int age;12 13 //姓名获取值14 public String getName() {15 return name;16 }17 18 //姓名设置值19 public void setName(String n) {20 name = n;21 }22 23 //年龄获取值24 public int getAge() {25 return age;26 }27 28 //年龄赋值29 public void setAge(int a) {30 age = a;31 }32 }33 34 //测试类35 class StudentTest {36 public static void main(String[] args) {37 //创建学生对象38 Student s = new Student();39 40 //使用成员变量41 //错误:被私有修饰了,外界不能直接访问了42 //System.out.println(s.name+"---"+s.age);43 System.out.println(s.getName()+"---"+s.getAge());44 45 //给成员变量赋值46 //s.name = "林青霞";47 //s.age = 27;48 //通过方法给赋值49 s.setName("林青霞");50 s.setAge(27);51 System.out.println(s.getName()+"---"+s.getAge());52 }53 }
6、this关键字
1 /* 2 我们曾经曰:起名字要做到见名知意。 3 4 this:是当前类的对象引用。简单的记,它就代表当前类的一个对象。 5 6 注意:谁调用这个方法,在该方法内部的this就代表谁。 7 8 this的场景: 9 解决局部变量隐藏成员变量10 */11 //定义学生类12 class Student {13 //姓名14 private String name;15 //年龄16 private int age;17 18 //姓名获取值19 public String getName() {20 return name;21 }22 23 //姓名设置值24 public void setName(String name) { //name = "林青霞";25 //name = name; //变量的使用规则:就近原则26 //这里是类名,目前还没有说过类似的用法,所以这个是有问题的27 //这里的调用只能通过对象名28 //这个对象如果存在,它应该代表的是Student的一个对象。29 //那么,谁能够代表当前类的对象呢? java就提供了一个关键字 this30 //Student.name = name;31 this.name = name;32 }33 34 //年龄获取值35 public int getAge() {36 return age;37 }38 39 //年龄赋值40 public void setAge(int age) {41 this.age = age;42 }43 }44 45 //测试类46 class StudentTest {47 public static void main(String[] args) {48 //创建学生对象49 Student s = new Student();50 51 //给成员变量赋值52 s.setName("林青霞");53 s.setAge(27);54 //获取数据55 System.out.println(s.getName()+"---"+s.getAge());56 }57 }
1 /* 2 标准的代码改进版 3 4 this:哪个对象调用那个方法,this就代表那个对象 5 */ 6 class Student { 7 private String name; 8 private int age; 9 10 public String getName() {11 return name; //这里其实是隐含了this12 }13 14 public void setName(String name) {15 this.name = name;16 }17 18 public int getAge() {19 return age;20 }21 22 public void setAge(int age) {23 this.age = age;24 }25 }26 27 class StudentTest2 {28 public static void main(String[] args) {29 //创建一个对象30 Student s1 = new Student();31 s1.setName("林青霞");32 s1.setAge(27);33 System.out.println(s1.getName()+"---"+s1.getAge());34 35 //创建第二个对象36 Student s2 = new Student();37 s2.setName("刘意");38 s2.setAge(30);39 System.out.println(s2.getName()+"---"+s2.getAge());40 }41 }
7、构造方法
1 /* 2 构造方法: 3 给对象的数据进行初始化 4 5 格式: 6 A:方法名与类名相同 7 B:没有返回值类型,连void都没有 8 C:没有具体的返回值 9 */10 class Student {11 private String name; //null12 private int age; //013 14 public Student() {15 System.out.println("这是构造方法");16 }17 }18 19 class ConstructDemo {20 public static void main(String[] args) {21 //创建对象22 Student s = new Student();23 System.out.println(s); //Student@e5bbd624 }25 }
1 /* 2 我们一直在使用构造方法,但是,我们确没有定义构造方法,用的是哪里来的呢? 3 4 构造方法的注意事项: 5 A:如果我们没有给出构造方法,系统将自动提供一个无参构造方法。 6 B:如果我们给出了构造方法,系统将不再提供默认的无参构造方法。 7 注意:这个时候,如果我们还想使用无参构造方法,就必须自己给出。建议永远自己给出无参构造方法 8 9 给成员变量赋值有两种方式:10 A:setXxx()11 B:构造方法12 */13 14 class Student {15 private String name;16 private int age;17 18 public Student() {19 //System.out.println("我给了,你还给不");20 System.out.println("这是无参构造方法");21 }22 23 //构造方法的重载格式24 public Student(String name) {25 System.out.println("这是带一个String类型的构造方法");26 this.name = name;27 }28 29 public Student(int age) {30 System.out.println("这是带一个int类型的构造方法");31 this.age = age;32 }33 34 public Student(String name,int age) {35 System.out.println("这是一个带多个参数的构造方法");36 this.name = name;37 this.age = age;38 }39 40 public void show() {41 System.out.println(name+"---"+age);42 }43 }44 45 class ConstructDemo2 {46 public static void main(String[] args) {47 //创建对象48 Student s = new Student();49 s.show();//null---050 System.out.println("-------------");51 52 //创建对象253 Student s2 = new Student("林青霞");54 s2.show();//林青霞---055 System.out.println("-------------");56 57 //创建对象358 Student s3 = new Student(27);59 s3.show();//null---2760 System.out.println("-------------");61 62 //创建对象463 Student s4 = new Student("林青霞",27);64 s4.show();//林青霞---2765 }66 }
8、成员方法
1 /* 2 类的组成:成员变量,成员方法 3 今天我们又加入了一个新的成员:构造方法。 4 以后再提类的组成: 5 成员变量 6 构造方法 7 成员方法 8 根据返回值: 9 void类型10 非void类型11 形式参数:12 空参方法13 非空参方法14 */15 class Student {16 public String getString() {17 return "helloworld";18 }19 20 public void show() {21 System.out.println("show");22 }23 24 public void method(String name) {25 System.out.println(name);26 }27 28 public String function(String s1,String s2) {29 return s1+s2;30 }31 }32 33 class StudentDemo {34 public static void main(String[] args) {35 //创建对象36 Student s = new Student();37 38 //调用无参无返回值方法39 s.show();40 41 //调用无参有返回值方法42 String result = s.getString();43 System.out.println(result);44 45 //调用带参无返回值的方法46 s.method("林青霞");47 48 //调用带参带返回值的方法49 String result2 = s.function("hello","world");50 System.out.println(result2);51 }52 }
9、创建对象做了哪些事情
10、练习
1 /* 2 定义一个类Demo,其中定义一个求两个数据和的方法, 3 定义一个测试了Test,进行测试。 4 5 变量什么时候定义为成员变量: 6 如果这个变量是用来描述这个类的信息的,那么,该变量就应该定义为成员变量。 7 8 变量到底定义在哪里好呢? 9 变量的范围是越小越好。因为能及时的被回收。10 */11 12 //方式113 /*14 class Demo {15 public int sum() {16 int a = 10;17 int b = 20;18 int c = a + b;19 return c;20 }21 }22 */23 //方式1满足了我们的要求,但是不好。24 //因为参与操作的数据现在是固定的。25 26 //方式227 /*28 class Demo {29 public int sum(int a,int b) {30 return a + b;31 }32 }33 */34 35 //方式2可以满足我们的要求,但是呢我们学习过来面向对象的思想。36 //我就再想,a,b可不可以定义为成员变量呢?37 //如果可以,我们再改进一版38 class Demo {39 int a;40 int b;41 42 public int sum() {43 return a + b;44 }45 }46 //虽然这种方式可以,并且好像是符合了面向对象的思想。47 //但是不好。48 //因为我们曾经说过:类是一组相关的属性和行为的集合。49 //并且类是通过事物转换过来的50 //而类中的成员变量就是事物的属性51 //属性是用来描述事物的52 //同理:成员变量其实是用来描述类的。53 54 //测试类55 class Test {56 public static void main(String[] args) {57 //创建对象58 //方式1测试59 /*60 Demo d = new Demo();61 System.out.println(d.sum());62 */63 64 //方式2测试65 /*66 Demo d = new Demo();67 int a = 10;68 int b = 20;69 System.out.println(d.sum(a,b));70 */71 72 //方式3测试73 Demo d = new Demo();74 d.a = 10;75 d.b = 20;76 System.out.println(d.sum());77 }78 }
11、static关键字
1 /* 2 定义一个人类 3 4 姓名和年龄都是变化的,这个我能接收,因为每个人的姓名和年龄是不同的。 5 但是,我们现在选取的几个人都是中国人,他们的国籍是一样的。 6 一样的国籍,我每次创建对象,在堆内存都要开辟这样的空间, 7 我就觉得有点浪费了。怎么办呢? 8 针对多个对象有共同的这样的成员变量值的时候, 9 Java就提高了一个关键字来修饰:static。10 */11 class Person {12 //姓名13 String name;14 //年龄15 int age;16 //国籍17 //String country;18 static String country;19 20 public Person(){}21 22 public Person(String name,int age) {23 this.name = name;24 this.age = age;25 }26 27 public Person(String name,int age,String country) {28 this.name = name;29 this.age = age;30 this.country = country;31 }32 33 public void show() {34 System.out.println("姓名:"+name+",年龄:"+age+",国籍:"+country);35 }36 }37 38 class PersonDemo {39 public static void main(String[] args) {40 //创建对象141 Person p1 = new Person("邓丽君",16,"中国");42 p1.show();//姓名:邓丽君,年龄:16,国籍:中国43 44 //创建对象245 //Person p2 = new Person("杨幂",22,"中国");46 //p2.show();47 Person p2 = new Person("杨幂",22);48 p2.show();//姓名:杨幂,年龄:22,国籍:中国49 50 //创建对象351 //Person p3 = new Person("凤姐",20,"中国");52 //p3.show();53 Person p3 = new Person("凤姐",20);54 p3.show();//姓名:凤姐,年龄:20,国籍:中国55 56 p3.country = "美国";57 p3.show();//姓名:凤姐,年龄:20,国籍:美国58 59 p1.show();//姓名:邓丽君,年龄:16,国籍:美国60 p2.show();//姓名:杨幂,年龄:22,国籍:美国61 }62 }
static内存图解:
1 /* 2 static的特点:(它可以修饰成员变量,还可以修饰成员方法) 3 A:随着类的加载而加载 4 回想main方法。 5 B:优先于对象存在 6 C:被类的所有对象共享 7 举例:咱们班级的学生应该共用同一个班级编号。 8 其实这个特点也是在告诉我们什么时候使用静态? 9 如果某个成员变量是被所有对象共享的,那么它就应该定义为静态的。10 举例:11 饮水机(用静态修饰)12 水杯(不能用静态修饰)13 D:可以通过类名调用14 其实它本身也可以通过对象名调用。15 推荐使用类名调用。16 17 静态修饰的内容一般我们称其为:与类相关的,类成员18 */19 class Student {20 //非静态变量21 int num = 10;22 23 //静态变量24 static int num2 = 20;25 }26 27 class StudentDemo {28 public static void main(String[] args) {29 Student s = new Student();30 System.out.println(s.num);31 32 System.out.println(Student.num2);33 System.out.println(s.num2);34 }35 }
1 /* 2 static关键字注意事项 3 A:在静态方法中是没有this关键字的 4 如何理解呢? 5 静态是随着类的加载而加载,this是随着对象的创建而存在。 6 静态比对象先存在。 7 B:静态方法只能访问静态的成员变量和静态的成员方法 8 静态方法: 9 成员变量:只能访问静态变量10 成员方法:只能访问静态成员方法11 非静态方法:12 成员变量:可以是静态的,也可以是非静态的13 成员方法:可是是静态的成员方法,也可以是非静态的成员方法。14 简单记:15 静态只能访问静态。16 */17 class Teacher {18 public int num = 10;19 public static int num2 = 20;20 21 public void show() {22 System.out.println(num); //隐含的告诉你访问的是成员变量23 System.out.println(this.num); //明确的告诉你访问的是成员变量24 System.out.println(num2);25 26 //function();27 //function2();28 }29 30 public static void method() {31 //无法从静态上下文中引用非静态 变量 num32 //System.out.println(num);33 System.out.println(num2);34 35 //无法从静态上下文中引用非静态 方法 function()36 //function();37 function2();38 }39 40 public void function() {41 42 }43 44 public static void function2() {45 46 }47 }48 49 class TeacherDemo {50 public static void main(String[] args) {51 //创建对象52 Teacher t = new Teacher();53 t.show();54 System.out.println("------------");55 t.method();56 }57 }