7.1 概述
Java语言是一种面向对象的程序设计语言,而面向对象思想是一种程序设计思想,我们在面向对象思想的指引下, 使用Java语言去设计、开发计算机程序。Java Object Oriented Programming(JavaOOP)
用Java语言来模拟真实的世界,用一系列相关的数据来进行描述的过程。
- 种类,是一种抽象的概念 (类) class 类名, 类型==种类
- 具体的事物,是一种具象的概念 (对象) 万事万物都是对象 类名 对象名=new 类名(); Scanner input= new Scanner(System.in)
种类,会规则有哪些属性,种类模板
对象,基于模板创建的,对象是具体的事物,不同的对象的属性值可能不一样,也有可能一样
7.2 语法
代码语言:javascript复制创建类:
public class 类名{
属性
方法
}
创建对象:
类名 对象名=new 类名();
7.3 属性和方法
属性: 就是定义变量,要看现在定义的类是干嘛用的, people人类,姓名,年龄,身高,性别,国籍,地址.........,属性都于名词相关,属性就用来规定这个种类有哪些名词来描述。
方法:就是定义方法, 方法与动词,动作相关,有关一切动作的代码,比如:input.nextInt(); System.out.println();if() while(); random.nextInt(); 都得放到方法中。
描述: 创建一个人类,有姓名,年龄,性别,身高这四个属性,有睡觉,吃饭,学习这几个功能
代码语言:javascript复制public class People {
//定变量 , 一般情况下类中的属性不需要赋值 成员属性
String name;
char gender;
int age;
double height;
//定方法 现在定义方法不需要再加static 成员方法
public void eat(){
System.out.println("吃饭");
}
public void sleep(){
System.out.println("睡觉");
}
public void study(){
System.out.println("学习");
}
}
类中的属性一般称为成员属性,类中的方法一般称为成员方法(不带static),静态属性和静态方法直接使用类名.属性名或类名.方法名()进行调用 。
7.4对象的使用
.点操作符,对象要调用属性和方法时都要使用点(.) input.nextInt(); random.nextInt(); System.out.println();
代码语言:javascript复制语法:
对象名.属性名; //调用属性
对象名.属性名=值; //为属性赋值
System.out.println(对象名.属性名); //使用属性值
对象名.方法名(); //调用
程序从main方法开始执行,main是程序执行的入口,所我们还是要在入口去写代码
代码语言:javascript复制public class Main {
public static void main(String[] args) {
//创建对象
People zhangpeng = new People();
/*
调用属性
*/
zhangpeng.name="张鹏";
zhangpeng.age=25;
zhangpeng.gender='男';
zhangpeng.height=179;
zhangpeng.sleep();
zhangpeng.eat();
zhangpeng.study();
zhangpeng.show();
System.out.println("=================================================================");
People xxl = new People();
xxl.name="谢兴灵";
xxl.age=26;
xxl.gender='男';
xxl.height=175;
xxl.sleep();
xxl.eat();
xxl.study();
xxl.show();
}
}
从以上代码应该有两个问题:
1、类中的方法没有static main为什么能调用
代码语言:javascript复制public class Main10 {
public static void main(String[] args) {
int index = searchNum(search);
}
public static int searchNum(int search){
int[] nums=new int[10];
Random random=new Random();
for (int i = 0; i < nums.length; i ) {
nums[i]=random.nextInt(100) 1;
System.out.println(nums[i]);
}
for (int i = 0; i < nums.length; i ) {
if(nums[i]==search){
return i;
}
}
return -1;
}
}
结论:这里是对方法进行直接调用,这种调用方式当前的这个方法必须和调用处在同一文件中,因为main方法是静态的,所以直接调用的话这个调用方法也必须是静态的
代码语言:javascript复制public class Main {
public static void main(String[] args) {
People zhangpeng = new People();
zhangpeng.name="张鹏";
zhangpeng.age=25;
zhangpeng.gender='男';
zhangpeng.height=179;
zhangpeng.sleep();
zhangpeng.eat();
zhangpeng.study();
zhangpeng.show();
}
}
这里使用的是对象名.方法名()的形式再进行调用,代表的是这个对象在这执行这个方法对应的功能
2、类中的方法使用属性的值时,为什么是main那边设置的结果
对象只要new就会创建一个堆空间,这个空间中存放的就类中的属性和方法
分析图片写出类
代码语言:javascript复制public class Dog {
//定变量
String color;
String breed;
String name;
int age;
String greder;
//定方法
public void eat(){
System.out.println(name "吃饭");
}
public void sleep(){
System.out.println(name "睡觉");
}
public void wang(){
System.out.println(name "叫");
}
public void show(){
System.out.printf("昵称:%s,品种:%s,颜色:%s,年龄;%d,性别:%s",name,breed,color,age,greder);
}
}
public class Main1 {
public static void main(String[] args) {
Dog dog=new Dog();
dog.breed="中华田园犬";
dog.color="黄色";
dog.name="大黄";
dog.greder="公";
dog.age=3;
dog.eat();
dog.sleep();
dog.wang();
dog.show();
}
}
问题1:如果在main方法中没有为对象的属性赋值?
如果没赋值,属性有默认值,与数组一样详情参照6.2中的表。因为数组的元素存放的地方是堆,类的成员变量存放的地方也是堆,由此可见,堆中的数据是有默认值的。
问题2: 类中String name;的定义与main方法中的String name定义有何区别?
代码语言:javascript复制public class Main1 {
public static void main(String[] args) {
int age;
}
}
public class Dog {
int age;
}
局部变量和全局变量的区别,什么叫局部变量只在定义它的这对大括号中起作用,全局变量,全局都起作用(所谓全局就是在能定义对象的方地),局部变量存放在栈中(方法中定义的变量在栈中),全局变量存放在堆中(类的成员变量在堆中) 局部变量与成员变量(全局变量)同名时,优先使用局部变量
7.5 构造方法
构造方法,每一个类必须有的一个方法,如果没写默认存在,构造方法的名称与类名一样,没有返回值的概念,作用就是用来创建对象或者在创建对象的时候给属性赋值(做初始化用),所以创建对象时都会调用构造方法。
默认构造,没有显示出来,
代码语言:javascript复制语法:
public 类名(){
}
代码语言:javascript复制public class Dog {
public Dog(String color1,String breed1,String name1,int age1,String greder1){
color=color1;
breed=breed1;
name=name1;
age=age1;
greder=greder1;
}
//定变量
String color;
String breed;
String name;
int age;
String greder;
}
public class Main1 {
public static void main(String[] args) {
Dog dog=new Dog();//这里报错现在
}
}
如果显示的把构造方法写出来了以后,默认构造不再起作用,如果以后还想再使用默认的构造怎么办
代码语言:javascript复制public class Dog {
//书写规范上有点问题 方法中的变量是局部变量
public Dog(String color1,String breed1,String name1,int age1,String greder1){
color=color1;
breed=breed1;
name=name1;
age=age1;
greder=greder1;
}
public Dog(){
}
}
把默认的构造方法再显示的写一遍
7.6 this关键字
this代表对象本身,哪个对象调用这个方法,这个方法中的this就代表调用那个对象。
这里的this是一个对象和dog对象一样,dog对象能做什么事,this就能做什么,只不能一般情况下只是用this来指明现在操作的是成员变量,每个类中都有this,它代表的就是当前这个类的对象
代码语言:javascript复制public class Dog {
public Dog(){
}
//构造方法的形参变量从书写规范上来说要与成员变量同名
public Dog(String color,String breed,String name,int age,String greder){
this.color=color;//当局部变量与成员变量同名的时候优先使用局部变量,这时成员要使用this进行指明
this.breed=breed;
this.name=name;
this.age=age;
this.greder=greder;
}
构造方法的形参变量从书写规范上来说要与成员变量同名,当局部变量与成员变量同名的时候优先使用局部变量,这时成员要使用this进行指明
7.7 方法重载
同样的方法名,根据不同的参数去完成不同的功能,怎样样才能形式重载
1、方法重载一定是发生在同一个类文件中
2、方法名必须相同
3、方法的参数必须不一样:
- 2.1 参数的个数不一样
- 2.2 同位置参数的类型不一样
public void eat(){
System.out.println(this.name "吃饭");
}
public void eat(String food){
System.out.println(this.name "吃" food);
}
public void eat(int n){
System.out.println(this.name "吃" n "斤肉");
}
public void eat(int n,String food){
System.out.println(this.name "吃" n "斤" food);
}
public void eat(String food,int n){
System.out.println("第二个两个参数的方法:" this.name "吃" n "斤" food);
}
不正确的重载一:
上面两个方法中参数名不一样,但是类型一样,这样无法重载,重载与参数名没关系
不正确的重载二:
方法重载与返回值没有关系
代码语言:javascript复制如果构造方法进行重构怎么写
反面案例,不要这样去对构造进行重载(方法里面的代码不要这样写)
public Dog(){ }
public Dog(String name){
this.name=name;
}
public Dog(String name,String breed){
this.name=name;
this.breed=breed;
}
public Dog(String name,String breed,String color){
this.name=name;
this.breed=breed;
this.color=color;
}
public Dog(String name,String breed,String color,int age){
this.color=color;
this.breed=breed;
this.name=name;
this.age=age;
}
正确的方式:
代码语言:javascript复制public Dog(){}
public Dog(String name){
this(name,null,null,0,null);
}
public Dog(String name,String breed){
this(name,breed,null,0,null);
}
public Dog(String name,String breed,String color){
this(name,breed,color,0,null);
}
public Dog(String name,String breed,String color,int age){
this(name,breed,color,age,null);
}
public Dog(String name,String breed,String color,int age,String greder){
this.color=color;
this.breed=breed;
this.name=name;
this.age=age;
this.greder=greder;
}
this()代表的是当前这个类的构造方法。
无参构造
public Dog(){}
全参构造
public Dog(String name,String breed,String color,int age,String greder){ this.color=color; this.breed=breed; this.name=name; this.age=age; this.greder=greder; }
全参构造就是将这个类中所有的属性都进行赋值操作,使用this()要保留这个全参构造.
最后留一句话: 方法重载发生在一个类中。
7.8 对象数组
代码语言:javascript复制public class Student {
String name;
String phone;
public String toString(){
return this.name "t" this.phone;
}
}
代码语言:javascript复制Student[] stus=new Student[3];
代码语言:javascript复制注意: Student[] stus=new Student[3]; 只是在内存中分配了三个连续的Student类型的空间,并没有具体的内容,所以不能对元素直接进行操作
错误案例:
public class Demo3 {
public static void main(String[] args) {
Student[] stus=new Student[3];
stus[0].name="张三";
stus[0].phone="13312345678";
System.out.println(stus[0]);
}
}
程序运行,会报空指针异常的错误,这就是因为stus[0]第一个元素并没有进行具体的赋值就开始使用,而造成的结果。
换种方式来讲:
代码语言:javascript复制public class Demo3 {
public static void main(String[] args) {
Student[] stus=new Student[3];
Student stu1;
Student stu2;
Student stu3;
}
}
stu1,stu2,stu3和 Student[] stus=new Student[3];本质上并无太大的差异,大家都知道stu1,stu2,stu3在没有具体赋值的情况下是不能使用的。所以Student[] stus=new Student[3];与stu1,stu2,stu3情况是一样的,没有具体赋值
结论:对象数组在使用的时候里面的元素一定要先赋值再使用。
正确的案例:
代码语言:javascript复制import java.util.Scanner;
public class Main2 {
public static void main(String[] args) {
//定义出一个三个长度的Student对象数组
Student[] stus=new Student[3];
Scanner input = new Scanner(System.in);
for (int i = 0; i < stus.length; i ) {
//为每一个元素进行具体的赋值
stus[i]=new Student();
System.out.println("请输入第" (i 1) "名同学的姓名:");
stus[i].name=input.next();//元素中的属性进行赋值
System.out.println("请输入第" (i 1) "名同学的电话:");
stus[i].phone=input.next();
}
System.out.println("姓名t电话");
for (Student stu : stus){
System.out.println(stu);
}
}
}
7.9 对象属性
就是在一个类中拥有另一个类的对象,例如
代码语言:javascript复制public class Student {
String name;
String phone;
Teacher teacher; //对象属性
public String toString(){
return this.name "t" this.phone "t" this.teacher;
}
}
对象属性可以在类中调用这个对象属性本身的属性和方法
在为对象属性赋值的时候,同样就先对对象属性进行new操作。
代码语言:javascript复制public class Demo4 {
public static void main(String[] args) {
Student stu=new Student();
stu.name="张三";
stu.phone="1333333333";
//单独创建老师对象
Teacher tea=new Teacher();
tea.name="李四";
tea.age=28;
tea.gender="男";
tea.subject="数学";
//将老师对象与学生对象中的teacher属性进行关联
stu.teacher=tea;
System.out.println(stu);
}
}
对象属性的访问
当前对象.对象属性.属性
代码语言:javascript复制public class Demo4 {
public static void main(String[] args) {
Student stu=new Student();
stu.name="张三";
stu.phone="1333333333";
Teacher tea=new Teacher();
tea.name="李四";
tea.age=28;
tea.gender="男";
tea.subject="数学";
stu.teacher=tea;
//通过当前对象对对象属性进行属性访问
System.out.println(stu.teacher.name);
System.out.println(stu.teacher.subject);
}
}
如果对象属性在定义的时候就已经new了,在使用的时候可以不再创建对象
代码语言:javascript复制public class Student {
String name;
String phone;
Teacher teacher=new Teacher(); //在定义的时候就已经new了
public void study(){
teacher.clazz();
System.out.println(this.name "开始认真的学习");
}
public String toString(){
return this.name "t" this.phone "t" this.teacher;
}
}
代码语言:javascript复制public class Demo4 {
public static void main(String[] args) {
Student stu=new Student();
stu.name="张三";
stu.phone="1333333333";
//因为在定义的时候已经创建了,所以可以直接访问对象属性中的属性
stu.teacher.name="李四";
stu.teacher.age=28;
stu.teacher.gender="男";
stu.teacher.subject="数学";
System.out.println(stu.teacher.name);
System.out.println(stu.teacher.subject);
}
}