目录
一、对象的一对一关系
两个对象之间一对一关系:
比如:一个英雄(Hero)对一个兵器(Weapon)
表达对象的一对一关系,其实就是把对象类型作为属性定义
双向一对一 :可以通过任意一方得到另一方的信息
单向一对一
public class OneToOne {
public static void main(String[] args) {
Husband h=new Husband("牛郎",'男');
Wife w=new Wife("织女",22);
//关联关系
h.setWife(w);
w.setHusband(h);
System.out.println(h.getName()+"的妻子是"+h.getWife().getName()+",她今年"+h.getWife().getAge()+"岁了。");
//输出:牛郎的妻子是织女,她今年22岁了。
}
}
/**
*
* 丈夫类
*
*/
public class Husband {
private String name;
private char sex;
private Wife wife;//关联妻子类,把对方的类作为自己的属性来表示
public Husband(String name, char sex) {
this.name = name;
this.sex = sex;
}
/**
* @return the name
*/
public String getName() {
return name;
}
/**
* @param name the name to set
*/
public void setName(String name) {
this.name = name;
}
/**
* @return the sex
*/
public char getSex() {
return sex;
}
/**
* @param sex the sex to set
*/
public void setSex(char sex) {
this.sex = sex;
}
public Wife getWife() {
return wife;
}
public void setWife(Wife wife) {
this.wife = wife;
}
}
/**
*
* 妻子类
*
*/
public class Wife {
private String name;
int age;
private Husband husband;//关联丈夫类,把对方的类作为自己的属性来表示
public Wife(String name, int age) {
this.name = name;
this.age = age;
}
/**
* @return the name
*/
public String getName() {
return name;
}
/**
* @param name the name to set
*/
public void setName(String name) {
this.name = name;
}
/**
* @return the age
*/
public int getAge() {
return age;
}
/**
* @param age the age to set
*/
public void setAge(int age) {
this.age = age;
}
public Husband getHusband() {
return husband;
}
public void setHusband(Husband husband) {
this.husband = husband;
}
}
二、static关键字修饰属性和方法
1、使用static关键字修饰一个属性
声明为static的变量实质上就是全局变量
public class Test{
public static void main(String[] args){
Role beibei = new Role("刘备","蜀国");
Role yunchang = new Role("云长","蜀国");
Role feifei = new Role("张飞","蜀国");
System.out.println(beibe.getInfo());
System.out.println(yunchang.getInfo());
System.out.println(feifei.getInfo());
}
}
//角色
class Role{
private String name;
private String country;
public Role(String name,String country){
this.name = name;
this.country = country;
}
public void setName(String name){
this.name = name;
}
public String getName(){
return name;
}
public void setCountry(String country){
this.country = country;
}
public String getCountry(){
return country;
}
public String getInfo(){
return "name="+name+",country="+country;
}
}
此时看内存情况,则发现内存有浪费,因为都是蜀国,蜀国存储了三遍;于是进行优化
public class Test{
public static void main(String[] args){
Role beibei = new Role("刘备");
Role yunchang = new Role("云长");
Role feifei = new Role("张飞");
System.out.println(beibe.getInfo());
System.out.println(yunchang.getInfo());
System.out.println(feifei.getInfo());
}
}
//角色
class Role{
private String name;
//优化后的定义
private static String country="蜀国"; //静态变量(全局变量)
public Role(String name,String country){
this.name = name;
this.country = country;
}
public void setName(String name){
this.name = name;
}
public String getName(){
return name;
}
public String getInfo(){
return "name="+name+",country="+country;
}
}
静态变量或方法不属于对象,依赖类;
静态变量是全局变量,生命周期从类被加载一直到程序结束;
静态变量只存一份,在静态方法区中存储;
静态变量是本类所有对象共享一份;
建议不要使用对象名去调用静态数据,直接使用类名调用;
static修饰一个方法,那么该方法属于类,不属于对象,直接用类名调用;
2、使用static关键字修饰一个方法
通常,在一个类中定义一个方法为static,那就是说,无需本类的对象即可调用此方法;
静态方法不能访问非静态的数据;
它只能调用其他的static方法;
它不饿能以任何方式引用this或super;
public class Test{
public static void main(String[] args){
Role beibei = new Role("刘备");
Role yunchang = new Role("云长");
Role feifei = new Role("张飞");
System.out.println(beibe.getInfo());
System.out.println(yunchang.getInfo());
System.out.println(feifei.getInfo());
}
}
//角色
class Role{
private String name;
//优化后的定义
private static String country="蜀国"; //静态变量(全局变量)
public Role(String name,String country){
this.name = name;
this.country = country;
}
public void setName(String name){
this.name = name;
}
public String getName(){
return name;
}
//静态方法不能访问非静态的数据
public static void setCountry(String country){
Role.country = country;
}
public String getInfo(){
return "name="+name+",country="+country;
}
}
使用static关键字修饰一个类以(后面介绍)
三、内存结构图与main方法与代码块
1、class文件加载到内存的结构图
2、main方法
主方法:
public static void main (String[] args){
// 代码块
}
public:公有的,最大的访问权限;
static:静态的,无需创建对象;
void: 表示没有返回值,无需向JVM返回结果;
main:方法名,固定的方法名
String[] args:表示参数为字符串数组,可以在调用方法时传入参数
3、代码块
普通代码块:直接写在方法中的代码块;
构造块:在类中定义的代码块;在创建对象时被调用,优于构造方法执行;
public class Test{
public static void main(String[] args){
Student s = new Student();
Student s1 = new Student();
}
}
class Student{
{
System.out.println("我是构造代码块");
}
public Student(){
System.out.println("我是构造方法");
}
public void study(){
//限制作用域
{
int i = 10;
System.out.println("我是普通代码块");
}
}
}
静态代码块: 在类中使用static声明的代码块称为静态代码块,
静态代码块,只执行一次,最先执行。
在第一次使用的时候被调用,只会执行一次,优于构造块;
在项目开发中通常会使用静态代码块来初始化只调用一次的数据。比如说:运行程序读取配置数据等;
public class Test{
public static void main(String[] args){
Student s = new Student();
Student s1 = new Student();
}
}
class Student{
static{
System.out.println("静态代码块");
}
{
System.out.println("构造块");
}
public Student(){
System.out.println("构造方法");
}
public void study(){
//限制作用域
{
int i = 10;
System.out.println("我是普通代码块");
}
}
}
四、单例设计模式
单例设计模式:保证一个类仅有一个实例,并提供一个访问它的全局访问点。
1、构造方法私有化
2、声明一个本类对象
3、给外部提供一个静态方法获取对象实例
1、两种实现方式
懒汉式:在第一次调用getInstance方法时,对象被创建,到程序结束后释放
饿汉式:在类被加载后,对象被创建,到程序结束后释放
public class Test{
public static void main(String[] args){
//Singleton1 s = new Singleton1();
Singleton1 s = Singleton1.getInstance();
s.print()
Singleton1 s1 = Singleton1.getInstance();
s1.print()
Singleton2 s = Singleton2.getInstance();
s.print()
Singleton2 s2 = Singleton2.getInstance();
s2.print()
}
}
//懒汉式
class Singleton2{
private Singlenton2(){}
private static Singleton2 s;
public static Singleton2 getInstance(){
if(s==null){
s = new Singleton2();
}
return s;
}
public void print(){
System.out.println("测试方法2");
}
}
//饿汉式
class Singleton1{
private Singlenton1(){}
private static Singleton1 s = new Singleton1();
public static Singleton1 getInstance(){
return s;
}
public void print(){
System.out.println("测试方法");
}
}
懒汉式:占用内存时间段,效率低(懒加载,延迟加载);在多线程可能会有安全问题;
饿汉式:占用内存时间长,效率高;
在项目中为什么要使用单例,单例有什么好处?
在设计一些工具类的时候(通常工具类,只有功能方法,没有属性)
工具类可能会被频繁调用
目的是为了节省重复创建对象所带来的内存消耗
2、Math代替单例
能否使用构造方法私有化+静态方法来替代单例?
class Tools{
private Tools(){};
public static void print1(){ }
public static void print2(){ }
}
五、对象数组案例
1、对象数组与管理
对象数组就是数组的每个元素都是类的对象,赋值时先定义对象,然后将对象直接赋值给数组。
public class Test{
public static void main(String[] args){
ChickenManager cm = new ChickenManager(5);
cm.add(new Chicken(1,"小小",10));
cm.add(new Chicken(2,"小二",8));
cm.add(new Chicken(3,"小三",6);
cm.add(new Chicken(4,"小四",4));
cm.add(new Chicken(5,"小五",2));
cm.add(new Chicken(6,"小六",1));
System.out.println("数组的长度:"+cm.length());
cm.printAll()
Chicken c = cm.find(5);
c.print();
cm.update(new Chicken(1,"小一",9));
cm.printAll();
}
}
//管理类
class ChickenManager{
private Chicken[] cs = null;
private int count = 0; //记录当前数组的元素个数(下标)
public ChickenManager(int size){
if(size>0){
cs = new Chicken[size];
}else{
cs = new Chicken[5];
}
}
public int length(){
return cs.length
}
//添加:实现动态数组
public void add(Chicken c){
if(count>=cs.length){ //表示数组满了,需要扩充
//算法一:扩充原来数组大小的一半 cs.length*3/2+1
//算法二: 扩充原来数组的一倍 cs.length*2
int newLen = cs.length*2 ;
cs=Arrays.copyOf(cs,newLen);
}
cs[count]=c;
count++;
}
//删除
public void delete(int id){
for(int i=0;i<count;i++){
if(cs[i].getId()==id){
//找到了要删除的对象,把该对象之后的对象向前移动一位
for(int j=i;j<count-1;j++){
cs[j] = cs[j+1];
}
//把最后一个对象赋值为空
cs[count-1]=null;
count--;
break;
}
}
}
//更新
public void update(Chicken c){
Chicken temp = find(c.getId());
if(temp!=null){
temp.setName(c.getName());
temp.setAge(c.getAge());
}
}
//查找
public Chicken find(int id){
for(int i=0;i<count;i++){
if(cs.[i].getId==id){
return cs[i];
}
}
return null;
}
//输出所有
public void printAll(){
for(int i=0;i<count;i++){
cs[i].print();
}
}
}
//小鸡类(数据对象) value object (VO)也可叫实体
class Chicken{
private int id;
private String name;
private int age;
public Chicken(){}//一般情况最好保留默认的构造方法
public Chicken(int id,String name,int age){
this.id = id;
this.name = name;
this.age = age;
}
public void setId(int id){
this.id = id;
}
public int getId(){
return id;
}
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;
}
}
动态数组:
数组是一种线性数据结构;
数组不适合删除插入等操作,适合添加和查找,遍历;