总结:万物皆对象,把一个东西抽象成一个对象,描述这个东西的属性(特征),方法(行为)
person类:
public class Person { //属性,成员变量,类的成员变量可以先声明,不用初始化,类成员变量是有默认值 String name;//姓名,String的默认值是null int age;//年龄,int的默认值是0 //行为,方法,也叫函数 /** * 打印姓名 */ public void showName(){//方法的名称如果是多个单词,首个的单词的首字母小写,其他的单词首字母大写,这样就像一个驼峰一样,所有叫驼峰命名法 System.out.println("姓名:" + name); getAge();//同一个类中,所有的方法可以直接互相调用,不用new去实例化对象 // public void xx(){}//方法中不能再定义方法 } /** * 获取年龄 * @return */ public int getAge(){//如果是一个有返回值的方法,那么方法体的最后一行一定是返回相应的数据,使用return关键字,返回的数据类型与方法定义的一致 return age;//方法上定义的int是返回值的类型,return后面跟的是方法的返回值 } }
Animal类:
public class Animal { String name;//动物的名称 int eye;//眼睛的个数 int legs;//几条腿 /** * 输出动物吃的食物 * @param food 食物 */ public void eat(String food){//String food这个叫方法的参数,方法的参数可以有多个,参数之间用,分隔 System.out.println("此种动物的食物是:" + food); } /** * 动物的移动方式 * @param moveType 移动方式 */ public void move(String moveType){ int i = 0; System.out.println("此种动物的移动方式是:" + moveType); } }
创建完上面的类后,创建对象:
public class Test1 { public static void main(String[] args){ // //实例化Person类,也就是创建Person对象 Person person = new Person();//声明一个Person类型的变量,变量名person,实例化Person类并且给person赋值,赋值的值就是当前的实例 // //new Person()就是实例化Person类 person.name = "张三";//给person对象的name属性赋值 person.showName();//对象的方法的调用 int i = person.getAge();//有返回值的方法,在调用之后就会有一个值,这个值就是方法中return的那部分 System.out.println(i);//打印默认年龄 person.age = 11;//给person对象的age属性赋值 int a = person.getAge(); System.out.println(a); //实例化一个Animal的对象 Animal ani = new Animal(); ani.eat("老鼠"); ani.move("飞"); //未来可能会学习更加复杂的类,我们会给这类创建对象,并且使用对象, //对于对象的使用无外乎就两个地方,操作对象的变量,调用类方法 } }
总结:
未来可能会学习更加复杂的类,我们会给这类创建对象,并且使用对象,
对于对象的使用无外乎就两个地方,操作对象的变量,调用类方法
修饰符最大的好处:声明该属性的访问范围,保证了数据的安全性、隔离性、封装性。
比如当属性修饰符为private,其他类就无法访问该属性(私有的类变量不能通过对象.属性的方式调用),可以通过set和get方法声明该属性的读写权限。
当为public时,其他类也可以访问该属性,不能确保数据安全性,用户可以随时修改属性,造成异常。
例子:
public class Person1 { Person person = new Person();//在类中可以创建对象,但是访问不了该对象的属性 // person.name;//这种方式报错,访问不了属性,没找到原因,name是public修饰的 { String name = "?";//代码块局部变量 1 } static String names = "?";//这种就是类变量(也称为静态变量)可以 类名.变量名使用,也是成员变量 2 public static void main(String[] args) {//这里的args就是形参,也是局部变量1 int i = 0; //这里的i就是方法体 局部变量 1 Person person = new Person();//实例化对象 person.name = "?"; //实例变量,只能实例化对象后才能使用,也是成员变量 2 } }
如果不了解代码块,详细:代码块
例子:
练习:创建一个有属性/方法的学生类,并打印该学生信息。
import java.util.Arrays; public class Student { private String name; private int age; private String [] course;//字符串数组 private String[] hobbies; //无参构造 public Student() {} //有参构造器赋值 public Student(String name, int age, String[] course, String[] hobbies) { super();//这里可以直接去掉,因为不需要object父类的方法,如果要使用到父类的构造器就需要使用super() this.name = name; this.age = age; this.course = course; this.hobbies = hobbies; } //打印学生个人信息 public String toString() { return "Student [name=" + name + ", age=" + age + ", course=" + Arrays.toString(course) + ", hobbies=" + Arrays.toString(hobbies) + "]"; } public static void main(String[] args) { String [] course = {"语文","数学"};//这里之所以创建一个数组,而不是直接在构造器中赋值,是因为语法不支持直接传递一个数组,必须间接传递一个数组变量 String [] hobbies = {"篮球","足球"}; Student student = new Student("zs",18,course,hobbies); System.out.println(student.toString()); } }
public class Person { String name; int age; String sex; public void study() { System.out.println("studying"); } public void showAge() { System.out.println("age:"+age); } //传递多少岁数,就加多少 public int addAge(int i) { return age+=i; } public static void main(String[] args) { Person person1 = new Person(); Person person2 = new Person(); System.out.println(person1 == person2);//false 不同对象之间就算属性方法一致,内存地址始终不一样,每new一次都会给一个对象分配内存空间 } }
public class Circle { //计算圆的面积公式 : 3.14*r*r /** * * @param r圆的半径 * @return 返回圆面积 */ public double area(double r) { return 3.14*r*r; } public static void main(String[] args) { //使用匿名对象调用方法 System.out.println(new Circle().area(2)); } }
例如:
例子:
public class Add { //多个相同名称的方法如果在一个类中共存,那么这些同名方法一定是参数的个数/数据类型不相同 //这样的同名方法就叫做 方法的重载 //重载机制:调用重载方法时,根据传递的参数列表(参数个数/数据类型)决定调用哪个重载方法,而不是根据返回值类型 public int add(int x ,int y) { return x+y; } public int add(int x ,int y,int z) { return x+y+z; } public double add(double x , double y) { return x+y; } public double add(double x , double y, double z) { return x+y+z; } public static void main(String[] args) { Add add = new Add(); add.add(1.1, 2.3);//这里调用的是两个double类型的重载方法 } }
public class Mol { public int mOL(int i) { return i*i; } public int mOL(int i , int j) { return i*j; } public String mOL(String i) { return i; } public static void main(String[] args) { Mol mol = new Mol();//实例化对象 System.out.println(mol.mOL(4)); System.out.println(mol.mOL(4,2)); System.out.println(mol.mOL("方法重载")); //这里说明一下关于同一类中不用实例化也可以调用其他方法 //那为什么在main里面要new一个对象才能用其他方法呢 //因为main方法有static修饰符,静态方法不可访问非静态方法 //同理,非静态方法只能调用非静态方法,不能调用静态方法 //如果想静态方法调用非静态方法,可以实例化对象,然后直接对象.方法调用 } }
public class Max { public int max(int i ,int j) { if(i > j) { return i; } else { return j; } } public double max(double i ,double j) { if(i > j) { return i; } else { return j; } } public double max(double i ,double j,double z) { if(i > j) { if(i > z) { return i; } else { return z; } } else { if(j > z) { return i; } else { return z; } } } public static void main(String[] args) { Max max = new Max(); System.out.println(max.max(4,3)); System.out.println(max.max(4.1,3.6)); System.out.println(max.max(4.12,3.32,2.23)); } }
例子:
public class Person3 { /** * 用数组的方式来传递可变个数的参数 * @param args */ public void printInfo(String[] args) {//问题,我们能够打印的信息都有源于方法的参数也就是形参的传递 //我们现在可能给方法要传递不同的参,但是我们不知道要给方法传递多少个参数(姓名/性别/年龄等等) for(int i = 0 ; i < args.length ; i++) { //方法一:可以定义一个数组接收可变参数,然后遍历参数 System.out.println(args[i]); } } /** * 用java特有的...的方式来传递可变个数的参数,这种参数在使用时和数组的使用方式相同 * @param args */ //java自带自定义参数格式: 数据类型... 变量名 ,如果还有其他参数,那么自定义参数必须放在最后声明 //例如:(String... args,int i)这种会报错,自定义参数必须放在最后声明 应为:(int i , String... args)才对 public void printInfo1(String... args) { for(int i = 0 ; i < args.length ; i++) { //方法二:可以定义一个 自定义参数列表 来接收可变参数,然后遍历参数 System.out.println(args[i]); } } public static void main(String[] args) { Person3 person = new Person3(); String[] ss = new String[]{"zhangsan","38"}; person.printInfo(ss); person.printInfo1(ss);//这两种输出结果一致 //这两种区别在于 传递参数是否可为null,数组如果不传递参数,需要传递一个null,而自带自定义参数列表不用传递任何值 // person.printInfo();//这里会报错,这里是数组,如果不传递参数时,必须传递一个null或空数组 person.printInfo1();//这里是自带的 自定义参数列表 } }
创建对象的内存分配过程:Person p = new Person(); p在栈中存储,而p存储着new Person()的内存地址,new Person()是存储在堆里面。内存地址起到了间接引用的作用。
方法的参数传递总结:
1、如果方法的形参是基本数据类型,那么实参(实际的数据)向形参传递参数时,就是直接传递值,把实参的值复制给形参。
2、如果方法的形参是对象/引用类型,那么实参(实际的对象),向形参传递参数时,也是把值给形参,不过这个值是实参在栈内存中的值,也就是引用对象在堆内存中的地址
基本数据类型都是保存在栈内存中,引用对象在栈内存中保存的是引用对象的堆地址,那么方法的参数传递是传递值(是变量在栈内存中的值)
简单来说,就是栈存储的值有两种,一种是基本数据类型的值,一种是堆内存的地址。修改基本数据的值不会影响原来传递的实参的值,但是如果是对象/引用类型如果修改了传递对象的属性/方法,那么就会影响到原来传递的实参的对象,因为原来的实参和传递过去的形参指向同一对象的堆内存地址,也就是使用的同一对象。
如果类中的属性定义为public那么属性任由调用者使用,会造成数据混乱,应该把数据封装起来
例子:这里用了同一类示范,假设是main方法是其他类的,这样就访问不了private私有属性,只能通过set/get方法访问
public class Test2 { public int age; private int legs; public void printAge() { System.out.println("年龄:"+age); } //可以把属性设置为私有化,通过set方法定义属性的范围,限制不正常的输入 public void setLegs(int legs) { if(legs >=0 && legs < 10) { this.legs = legs; } else { System.out.println("输入的腿的数量不正常"); } } //如果限制了用户属性,但是又要使用这个属性,可以设置get方法给用户获取该属性 public int getLegs() { return legs; } public static void main(String[] args) { Test2 test = new Test2(); test.age=-100;//这种情况,程序是对的,能执行,但不符合正常逻辑 //像这种情况,是把类的属性开发出来,让调用者随意使用,这样会有问题 test.printAge(); test.setLegs(-100);//限制了用户乱调用数据 test.setLegs(4); System.out.println(test.getLegs());//获取封装的属性 } }
//Person类 public class Person { private int age; public void setAge(int age) { if(age > 0 && age <=130) { this.age = age ; } else { System.out.println("年龄不合法"); } } public int getAge() { return age; } } //TestPerson类 public class TestPerson { public static void main(String[] args) { Person person = new Person(); person.setAge(-12); person.setAge(20); System.out.println(person.getAge()); } }
public class Person1 { private int age; /** * 如果定义了显式构造方法,那么new对象时就使用显示构造方法 * 如果定义了显示带参构造方法,不定义无参构造方法时,new Person1()这样就会报错,因为显示构造方法已经代替了默认的构造方法 * 所以如果定义了带参构造方法,最好定义多一个无参构造 * */ public Person1() {}//如果不定义有参构造方法,这个就是隐藏的构造方法,new对象时,调用这个方法 public Person1(int age) {//有参构造,创建对象时,就可以直接调用有参构造,因为这里定义了有参构成,所以需要重新定义无参构造 this.age = age; //this.age指当前类的age属性,后面的age是形参 } public static void main(String[] args) { //new对象的根本原理:就是通过类的构造方法 Person1 pe = new Person1();//new Person2()对象调用的是public Person1(){}方法,不过这个方法是隐藏的,默认构造器修饰符是根据类修饰符决定 } } class Person2{ // Person2() {} //Person2类前面修饰符是默认的,构造方法修饰符就是默认的 public static void main(String[] args) { Person2 pe = new Person2();//new Person2()对象调用的是Person2(){}方法 } }
总结:new对象其实就是调用类的构造方法
public class Person { private int age; private String name; public Person() {//定义默认构造器,初始年龄18 age = 18; } public Person(int age,String name) {//定义有参构造 this.age = age; this.name = name; } public static void main(String[] args) { Person p = new Person();//调用无参构造 Person p1 = new Person(13,"猪头");//调用有参构造 System.out.println(p.age); System.out.println(p1.age+","+p1.name); } }
public class Point { private int x,y,z; public Point(int x,int y,int z) { this.x = x; this.y = y; this.z = z; } public void setPoint(int x, int y, int z) { this.x = x; this.y = y; this.z = z; } public static void main(String[] args) { Point p = new Point(1, 2, 3);//生成具有特定坐标的点对象 p.setPoint(6, 7, 8);//提供了设置3个坐标的方法 } }
//TriAngle类 public class TriAngle { private int base;//底边长 private int height;//高 public TriAngle() {} public TriAngle(int base,int height) { this.base = base; this.height = height; } public int base() { return base; } public int height() { return height; } } //TestTriAngle类 public class TestTriAngle { public static void main(String [] args) { TriAngle angle = new TriAngle(5,5);//初始化底边和高 //三角形的面积公式 double area = (angle.base()*angle.height())/2.0; System.out.println(area); } }
public class Person8 { private String name; private String sex; private int age; private String hobbies; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getHobbies() { return hobbies; } public void setHobbies(String hobbies) { this.hobbies = hobbies; } @Override public String toString() { return "Person8 [name=" + name + ", sex=" + sex + ", age=" + age + ", hobbies=" + hobbies + "]"; } }
总结:JavaBean就是一个实体类,把属性/方法封装好,提供了设置和获取属性的方法(get/set方法).