六: 面向对象
6.1
-
c语言面向过程 ; java面向对象
-
面向对象主线及要素
-
设计类和类的对象
-
堆和栈
-
属性与局部变量
-
默认初始化值
language在小括号内,可以在调用是赋值;food不行; -
方法
-
对象是数组
package lei_test;
class A{
public static void main(String[]args) {
//声明Student类型的数组
Student[]arr=new Student [5];//String[]arr=new String[5]
for(int i=0;i<arr.length;i++) {
//给数组元素赋值
arr[i]=new Student();
arr[i].number=(i+1);
arr[i].state=(int)(Math.random()*(6-1+1)+1);
arr[i].score=(int)(Math.random()*(100-0+1));
}
for(int i=0;i<arr.length;i++)
System.out.println(arr[i].info());
System.out.print("************\n");
for(int i=0;i<arr.length;i++) {
if(arr[i].state==3)
System.out.println(arr[i].info());
}
System.out.print("************\n");
//冒泡排序
for(int i=0;i<arr.length-1;i++)
for(int j=0;j<arr.length-1-i;j++) {
if(arr[i].score<arr[i+1].score) {
int temp=arr[i].score;
arr[i].score=arr[i+1].score;
arr[i+1].score=temp;
}
}
for(int i=0;i<arr.length;i++)
System.out.println(arr[i].info());
}
}
class Student{
int number;
int state;
int score;
//显示学生信息的方法 如果在遍历时直接输出arr[i],则输出的是地址符
public String info() {
return "学号:"+number+",年级:"+state+",成绩:"+score;
}
}
- 数组对象的调用
- 说明
p1与p2是两个不同的地址;p3和p1
编译完源文件后生成一个或多个字节码文件
使用jvm中类的加载器和解释器对生成的字节码文件进行解释运行。意味着需要将字节码文件对应的类加载到内存中,(即放入栈或堆中),涉及到内存解析。 - 匿名对象(以下造的是两个不同的对象)
- 方法的重载
方法重载是让类以统一的方式处理不同类型数据的一种手段。多个同名函数同时存在,具有不同的参数个数/类型。
重载Overloading是一个类中多态性的一种表现。
- 可变个数形参的方法(int String等类型都适用且String类型与数组的作用相同)
public void mOL(String...strs) {
System.out.println("Hello");
}
public void mOL(String str) {
System.out.println("nihao");
}//当只有一个字符串 优先考虑第二个
public void show(int i,String ...str)//必须声明在形参的末尾
-
方法参数的值传递机制
-
方法的递归
-
题目
6.2关键字
1.this
1.1作用:可以用来修饰属性、方法、构造器,以区分属性和局部变量。
理解为当前对象或当前正在创建的对象
注:this.name表示当前对象相当于p.name
1.2:使用:
1.3.this调用构造器
1.3.1我们在类的构造器中,可以显式的使用“this(形参列表)”方式,调用本类中指定的其他构造器,但不能调用自己。
1.3.2如果一个类中有n个个体,则最多有n-1个构造器使用了“this(形参列表)”,避免调用成环
例题
package lei_test;
public class B {
public static void main(String[]args) {
BTest in=new BTest(12,"WangNan");
}
}
class BTest{
public int age;
public String name;
public BTest(int age) {
this.age=age;//调用属性
System.out.println(age+"Hello");
}
public BTest(int age,String name) {
this(age);//调用构造器
this.name=name;
System.out.println("名字为:"+name);
}
}
1.3.3规定:“this(形参列表)”必须声明在当前构造器的首行,所以一个构造器内部最多只能声明一个“this(形参列表)”用来调用其他构造器(调用两个则不能两个都放在首行)。
- 例题
package lei_test;
class BoyGirlTest{
public static void main(String[]args) {
Boy b=new Boy ();
b.setName("罗密欧"); b.setAge(21);
b.shout();
Girl g=new Girl();
g.setName1("朱丽叶");g.setAge1(18);
g.marry( b);
Girl g2=new Girl();
g2.setName1("祝英台");g2.setAge1(23);
if(g.compare(g2)>0)
System.out.println(g.getName1()+"大");
else if (g.compare(g2)<0)
System.out.println(g2.getName1()+"大");
else
System.out.println(g.getName1()+"和"+g2.getName1()+"一样大");
}
}
class Boy{
private String name;
private int age;
public void setName(String name) {
this.name=name;
}
public String getName() {
return name;
}
public void setAge(int age) {
this.age=age;
}
public int getAge() {
return age;
}
public void marry(Girl g) {//创建一个女孩类型的对象
System.out.println("我想娶"+g.getName1());
}
public void shout() {
if( this.age>22)//男孩的年龄
System.out.println("可以去登记结婚了");
else
System.out.println("再等等");
}
}
class Girl{
private String name1;
private int age1;
public void setName1(String name1) {
this.name1=name1;
}
public String getName1() {
return name1;
}
public void setAge1(int age1) {
this.age1=age1;
}
public int getAge1() {
return age1;
}
public void marry(Boy b) {
System.out.println("我想嫁"+b.getName());
b.marry(this);//在b中定义的方法是public void marry(Girl g),这里就只用写this,指代当前这个女孩
}
public int compare(Girl g2) {//两个女孩年龄进行比较,需要再创建一个对象
// if(this.age1>g2.age1) {
// return 1;
// else if(this,age1<g2.age1)
// return -1;
// else
// return 0;
// }//正数表示当前对象大;负数表示当前对象小;0表示当前对象与形参对象相等
return this.age1-g2.age1;
}
}
2.package
2.1作用:为了更好地实现项目种类的管理,提供了包的概念
2.2使用:声明类或接口所属的包,声明在源文件的首行
2.3注意:包,属于标识符,遵循标识符的命名规则(xxyyzz)
每“.”一次,就代表一层文件目录
同一个包下,不能命名同名的类或接口
不同包下,可以命名同名的接口、类
3.import(导入)
3.1 :作用:在源文件中显式的使用import结构导入指包下的类、接口
3.2 :位置:声明在包的声明和类的声明之间
3.3:注意:
3.3.1: 如果需要导入多个结构,则并列写出即可
3.3.2 :可以使用“xxx.*”的方式,表示可以导入xx包下所有的结构(类或接口),但不可表示子包,子包仍需要import
3.3.3: 如果使用的类或接口是java.lang包下(system.out.println)或本包下定义的,则可省略import结构。
3.3.4 :如果在源文件中使用了不同包中同名的类,则必须至少有一个类需要以全类名的方式显示
3.3.5 :import static :导入指定类或接口中的静态结构:属性或方法
import static java.lang.System.*;
out.println("hello");
- mvc设计模式
4.** super**
- this关键字现在本类中找,没找到再到父类中找;super直接到父类中找
- super调用构造器
- super调用方法和属性
- super和this关键字可以同时使用在同一个类中,但是super关键字要放在首行;
6.instanceof(向下转型前的判断)
7.static
静态方法中只能调用静态,如果要调用非静态,就要创建对象
- 自动生成编号
8.final
不能用于默认初始化(默认初始化都相同,final无意义)
不能用于方法初始化(构造器调完后,对象就出生了,对应的属性也就应该存在了,属性的值应该就要存在了,用对象调方法还在后面)
- 题目
++x对x重新复制改变了x得值,编译不通过;x+1没改变x的值,可以通过
变量o不可改变,但是o中的属性可以改变
9.abstract
构造器不能重写可以重载;
父类中的abstract方法需要子类重写,如果是private就无法重写,子类就无法实例化;static方法不能重写;final不能重写;
6.3object类中的方法
1:equals():
1.1equals与==的区别
- ==运算符
- equals()
equals是一个方法,只能用对象来调,所以只适用于引用数据类型
- String的equals方法只有在另一个对象是String的情况下才可能返回true,
而contentEquals只要求另一个对象是CharSequence或其子类的对象
5.我们自定义的类如果使用equals()的话,也通常是比较两个对象“实体内容”是否相同,那么我们就需要对object()进行重写
(手动重写)或者(“source0“”Generte hashCode ()and equals”)
class Order{
int orderld;
String orderName;
public int getOrderld() {
return orderld;
}
public void setOrderld(int orderld) {
this.orderld = orderld;
}
public String getOrderName() {
return orderName;
}
public void setOrderName(String orderName) {
this.orderName = orderName;
}
public Order(int orderld,String name) {
this.orderld=orderld;
this.orderName=name;
}
public boolean equals(Object obj) {
if(this==obj)//即定义的类就是Object
return true;
if(obj instanceof Order) {
Order Ord=(Order)obj;//强制转换为Order,则可以调用Order中的方法或属性
return this.orderld==Ord.orderld
&&this.orderName.contentEquals(Ord.orderName);}//或者写成this.orderName==Ord.orderName
//类比Sting a="aa";String b="aa";(a==b)true 因为aa的地址赋给了变量a、b
return false;
}
}
public class OrderTest{
public static void main(String[]args) {
Order order1=new Order(1001,"aa");
Order order2=new Order(1001,"aa");
System.out.println(order1.equals(order2));
}
}
public class K {
public static void main(String[]args) {
String a=new String("aa");
String b=new String("aa");
System.out.println(a==b);//false
//String a=new String("aa");
//String b=new String("aa");
//System.out.println(a==b);//true
}
}
- 比较
1:==是运算符;equals()是方法;
2:==可以用于基本数据类型(数据)和引用数据类型(地址)
equals()只能用于引用数据类型(Object类中是比较地址,但可以重写使其比较数据)
2:to String()
重写(手动实现)或(“source”“Generate toString”)
6.4包装类
使基本数据类型具有类的特征
- 基本数据类型转换为包装类
有时需要类类型的形参
布尔型:只要括号内是true,则返回true;若是false或其他值则为false;无论大小写都可以
boolean为基本数据类型;Boolean为包装类型
- 包装类转换为基本数据类型
包装类不可进行运算,而基本数据类型可以;
- 自动装箱和自动拆箱
- 基本数据类型转换为String
- String转换为基本数据类型
- 题目
三元运算符需要冒号两边类型统一;编译时问号后都编译,即将Integer转换为Double型
相当于m,n都放在范围在-128到127数组的缓存区内,每次定义直接从缓存去中取出,则地址值一样;若超出范围,则新建对象;
(注意数组中如果为char类型数组,则输出数组名就可以输出数组元素;其他类型均输出地址值)
import java.util.Scanner;
import java.util.Vector;
public class ScoreTest {
public static void main(String[]args) {
Scanner scan=new Scanner(System.in);
Vector v=new Vector();//向量
int maxScore=0;
for(;;) {
int score =scan.nextInt();//从键盘输入数进行循环
if(score<0)
break;
if(score>100) {
System.out.println("请重新输入:");
continue;
}
// Integer inscore=new Integer(score);
// v.addElement(inscore);
v.addElement(score);//自动装箱转换为包装类作为形参
if(maxScore<score)
maxScore=score;
}
char level='0';
for(int i=0;i<v.size();i++) {
Object obj=v.elementAt(i);//取出向量中的元素
Integer inscore=(Integer)obj;//将数据转为Integer型,便于使用intValue()方法
int score=inscore.intValue();//将数据转换为基本类型才可以运算
if(maxScore-score<=10)
level='A';
else if(maxScore-score<=20)
level='B';
else if(maxScore-score<=30)
level='C';
System.out.println("student"+i+"score is"+score+",level is"+level);
}
}
}
6.5单例设计模式
1:单例的饿汉式
2:单例的懒汉式(延迟对象的创建)
线程安全的单例模式之懒汉模式:
同步代码块:
同步方法:
- main()方法
一个源文件中只能有一个public类,但是不同的类中可以同时有main()方法;
可以实现与控制台的转换:
main()方法中的形参都是字符串类型
run as(先用上面的编译,再用下面的赋值Arguments-Program arguments)
package test;
class SingleTest{
public static void main(String[] args) {
for(int i=0;i<args.length;i++)
System.out.println("****"+args[i]);
}
}
6.6代码块
- 题目
package test;
class Person{
static
{
System.out.println("1");
}
{
System.out.println("2");
}
public Person() {
System.out.println("3");
}
}
public class SingleTest extends Person{
static {
System.out.println("4");
}
{
System.out.println("5");
}
public SingleTest() {
System.out.println("6");
}
public static void main(String[] args) //在方法体内部调用main()方法,对象为SingleTest
{
System.out.println("7");
System.out.println("**********");
new SingleTest();
System.out.println("**********");
new SingleTest();
}
}
6.7抽象类与抽象方法
static类就可以调,而abstract需要子类重写,用对象来调且方法无方法体;
创建抽象类的匿名子类对象
package NiMing;
public class Creature {
public static void main(String[]args) {
// new Student("wang",13);//匿名对象;非匿名的类
// Student a=new Student("wang",24);
// a.breath();//非匿名的对象非匿名的类
Person b=new Person() {//创建匿名子类非匿名对象
public void eat() {
System.out.println("人吃饭");}
public void breath() {
System.out.println("人呼吸");}
};
new Person () {//创建匿名子类匿名对象
public void eat() {
System.out.println("人多吃饭");}
public void breath() {
System.out.println("人要呼吸");}
};
}
}
比如抽象类都继承了Object类(非抽象类)
6.8接口
- 题目
- 例题
6.9:内部类
- 4