笔记目录:(https://www.cnblogs.com/wenjie2000/p/16378441.html)
●使用现有技术解决
张老太养了两只猫猫:一只名字叫小白,今年3岁,白色。还有一只叫小花,今年100岁,花色。请编写一个程序,当用户输入小猫的名字时,就显示该猫的名字,年龄,颜色。如果用户输入的小猫名错误,则显示张老太没有这只猫猫。
1)单独的定义变量解决
2)使用数组解决
//单独变量来解决=>平利于数据的管理
//第1只猫信息
String cat1Name = "小白";
int cat1Age = 3;
String cat1Color ="白色";
//第2只猫信息
String cat2Name = "小花";int cat2Age = 100;
String cat2Color ="花色";
//数组===>(1)数据类型体现不出来(2)只能通过[下标]获取信息,造成变量名字和内容
// 的对应关系不明确(3)不能体现猫的行为
//第1只猫信息
String[] cat1 = {"小白","3","白色"};
String[] cat2 ={"小花","100","花色"};
●现有技术解决的缺点分析
不利于数据的管理
效率低
===》 引出我们的新知识点类与对象哲学,道家思想
java设计者引入类与对象(OOP),根本原因就是现有的技术,不能完美的解决新的新的需求.
●类与对象的关系示意图

●上图说明
注意:从猫类到对象,目前有几种说法:1.创建一个对象⒉.实例化一个对象3.把类实例化...
当然:上面的猫也可是鱼、狗、人... java最大的特点就是面向对象。
public class HelloWorld{
public static void main(String []args){
//1. new Cat()创建一只猫
//2.Cat cat1 = new Cat();把创建的猫赋给cat1
//3. cat1就是一个对象
Cat cat1 = new Cat();
cat1.name ="小白";
cat1.age = 3;
cat1.color ="白色";
//创建了第二只猫,并赋给cat2
// cat2 也是一个对象(猫对象)
Cat cat2 = new Cat();
cat2.name ="小花";
cat2.age = 100;
cat2.color ="花色";
//怎么访问对象的属性呢
System.out.println("第1只猫信息" + cat1.name +" " +cat1.age + " "+ cat1.color);
System. out.println("第2只猫信息"+ cat2.name +" " + cat2.age + " " + cat2.color);
}
}
//使用面向对象的方式来解决养猫问题
//
//定义一个猫类Cat ->自定义的数据类型
class Cat {
//属性
String name;//名字
int age;//年龄
String color;//颜色
//行为
}
●类和对象的区别和联系
通过上面的案例和讲解我们可以看出:

属性/成员变量
基本介绍
●注意事项和细节说明
属性的定义语法同变量,示例:访问修饰符属性类型属性名;
属性的定义类型可以为任意类型,包含基本类型或引用类型
属性如果不赋值,有默认值,规则和数组一致。
●基本语法
对象名.属性名;
案例演示赋值和输出
cat.name ;
cat.age;
cat.color;
●看一个思考题
我们定义一个人类(Person)(包括名字,年龄)。
//我们看看下面一段代码:
Person p1=new Person();
p1.age=10;
p1.name="小明";
Person p2=p1;//把p1赋给了p2, 让p2指向p1
System.out.println(p2.age);
//请问:p2.age究竟是多少?并画出内存图:
//10

●Java内存的结构分析
1.栈:一般存放基本数据类型(局部变量)
2.堆:存放对象(Cat cat,数组等)
3.方法区:常量池(常量,比如字符串),类加载信息
4.示意图[Cat (name, age, price)
●Java创建对象的流程简单分析
Person p = new Person();
p.name = "jack” ;
p.age = 10
1.先加载Person类信息(属性和方法信息,只会加载一次)
2在堆中分配空间,进行默认初始化(看规则)
3.把地址赋给p,p就指向对象
4.进行指定初始化,比如p.name =" jack" p.age = 10
●看一个练习题,并分析画出内存布局图,进行分析
//我们看看下面一段代码,会输出什么信息:
Person a=new Person();
a.age=10;
a.name="小明";
Person b;
b=a;
System.out.println(b.name);
b.age=200;
b = null;
System.out.println(a.age);
System.out.println(b.age);
/*
小明
200
b.age会出现异常.
*/

基本介绍
在某些情况下,我们要需要定义成员方法(简称方法)。比如人类:除了有一些属性外(年龄,姓名..),我们人类还有一些行为比如:可以说话、跑步..,通过学习,还可以做算术题。这时就要用成员方法才能完成。现在要求对Person类完善。
添加speak成员方法,输出我是一只好人
添加cal01成员方法,可以计算从1+...+1000的结果
添加cal02成员方法,该方法可以接收一个数n,计算从1+...+n 的结果
添加getSum成员方法,可以计算两个数的和
public class HelloWorld{
public static void main(String []args){
//方法使用
//1方法写好后,如果不去调用(使用),不会输出
//2.先创建对象,然后调用方法即可
Person p1 = new Person();
p1.speak();//调用方法
p1.cal01();//调用cal01方法
p1.cal02(5);//调用cal02方法
//调用getSum方法,同时num1=10, num2=20
//把方法 getsum返回的值,赋给变量 returnRes
int returnRes = p1.getSum(10,20);
System.out.println("getsum方法返回的值=" + returnRes);
}
}
class Person {
String name;
int age;
//方法(成员方法)
//添加speak成员方法,输出“我是一个好人”
//解读
//1.public 表示方法是公开
//2.void :表示方法没有返回值
//3.speak() : speak是方法名,()形参列表
//4.方法体,可以写我们要执行的代码
//5.System.out.println("我是一个好人");表示我们的方法就是输出一句话
public void speak(){
System.out.println("我是一个好人");
}
//添加cal01 成员方法,可以计算从1+..+1000的结果
public void cal01(){
//循环完成
int res = 0;
for(int i = 1; i <= 1000; i++) {
res += i;
}
System.out.println("计算结果=" + res);
}
//添加cal02成员方法,该方法可以接收一个数n,计算从1+...+n的结果
//解读
//1. (int n)形参列表,表示当前有一个形参n,可以接收用户输入
public void cal02(int n){
//循环完成
int res = 0;
for(int i = 1; i <= n; i++){
res += i;
}
System.out.println("cal02计算结果="+ res);
}
//添加getsum成员方法,可以计算两个数的和//老韩解读
//1. public 表示方法是公开的
//2. int :表示方法执行后,返回一个int 值
// 3. getsum方法名
//4. (int num1, intTum2)形参列表,2个形参,可以接收用户传入的两个数
public int getSum(int num1, int num2) {
int res = num1 +num2;
return res;
}
}
提示:画出程序执行过程[getSum]+说明

●看一个需求:
请遍历一个数组,输出数组的各个元素值。
✔解决思路1,传统的方法,就是使用单个for循环,将数组输出,大家看看问题是什么?
✔解决思路2:定√义一个类 MyTools ,然后写一个成员方法,调用方法实现,看看效果又如何。
成员方法的好处
✔提高代码的复用性
✔可以将实现的细节封装起来,然后供其他用户来调用即可.
访问修饰符 返回数据类型 方法名 (形参列表..){//方法体
语句;
return 返回值;
}
●访问修饰符(作用是控制方法使用的范围)
可选,[有四种:?],具体在后面说
●返回类型
●方法名
遵循驼峰命名法,最好见名知义,表达出该功能的意思即可,比如得到两个数的和getSum,开发中按照规范
●形参列表
●方法体
里面写完成功能的具体的语句,可以为输入、输出、变量、运算、分支、循环、方法调用,但里面不能再定义方法!即:方法不能嵌套定义。[演示]
●方法调用细节说明
方法的传参机制对我们今后的编程非常重要,一定要搞的清清楚楚明明白白。我们通过案例来学习。
●基本数据类型的传参机制
public class HelloWorld{
public static void main(String []args){
int a = 10;int b = 20;
//创建AA对象名字 obj
AA obj = new AA();
obj.swap(a,b);//调用swap
System.out.println( "main方法a=" +a+ " b=" + b); //a=10 b=20
}
}
class AA {
//同一个类中的方法调用:直接调用即可/ /
public void swap(int a,int b) {
System.out. println("\na和b交换前的值\na=" + a + "\tb=" + b);//a=10 b=20
//完成了a 和b的交换
int tmp = a;
a = b;
b = tmp;
System.out.println("\na和b交换后的值\na=" + a + "\tb=" + b);//a=20 b=10
}
}
//swap方法会创建不同的栈。其中的变量a,b所对应的地址也不同,因此不会改变。
●引用数据类型的传参机制
public class HelloWorld{
public static void main(String []args){
//测试
B b = new B();
int[ ] arr = {1,2,3};
b.test100(arr);//调用方法
System.out. println( " main的arr数组");//逼历数组
for(int i = 0; i < arr. length; i++) {
System.out.print(arr[i] +"\t");
}
System.out.println();
}
}
class B {
//B类中编写一个方法test100,
//可以接收一个数组,在方法中修改该数组,看看原来的数组是否变化
public void test100(int[] arr) {
arr[0] = 200;//修改元素
//遍历数组
System.out.println( "test100的arr数组");
for(int i = 0; i <arr. length; i++){
System.out.print(arr[i] +"\t");
}
}
}
//数组为应用类型,调用test100产生新栈时传入的是arr在堆中的地址而不是拷贝数组,因此修改arr时是对同一空间进行操作。所以会改变
// import java.util.Scanner;
public class HelloWorld{
public static void main(String []args){
B b = new B();
Person p = new Person();
p.name = "jack" ;
p.age = 10;
b.test200(p);
System.out.println( "main的p.age=" + p.age);
}
}
class Person {
String name;
int age;
}
class B {
public void test200 (Person p) {
p.age = 10000;//修改对象属性
}
}
●基本介绍
简单的说:递归就是方法自己调用自己,每次调用时传入不同的变量.递归有助于编程者解决复杂问题,同时可以让代码变得简洁
递归能解决什么问题?
●八皇后问题说明
八皇后问题,是一个古老而著名的问题,,是回溯算法的典型案例。该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即:任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。
/*
●八皇后思路分析,老韩说下
1)第一个皇后先放第一行第一列
2)第二个皇后放在第二行第一列、然后判断是否OK,如果不OK,继、续放在第二列、第三列、依次把所有列都放完,找到一个合适
3)继续第三个皇后,还是第一列、第二列.…..直到第8个皇后也能放在一个不冲突的位置,算是找到了一个正确解
4)当得到一个正确解时,在栈回退到上一个栈时,就会开始回溯,即将第一个皇后,放到第一列的所有正确解,全部得到.
5)然后回头继续第一个皇后放第二列,后面继续循环执行1,2.3.4的步骤
说明:理论上应该创建一个二维数组来表示棋盘,但是实际上可以通过算法,用一个一维数组即可解决问题. arr[8] ={0,4, 7,5.2,6,1,3}//对应arr下标表示第几行,即第几个皇后,arri] = val , val表示第i+1个皇后,放在第i+1行的第val+1列
*/
public class HelloWorld{
public static void main(String []args){
B b = new B();
int huang[]=new int[8];
System.out.println(b.test200(huang,0));
}
}
class B {
public int test200 (int[] huang,int i) {
if(i>7){
return 1;
}else{
int m=0;
for(int j=1;j<=8;j++){
if(aa(huang,j,i)){//不冲突
huang[i]=j;
m+=test200(huang, i+1);
}
}
return m;
}
}
public boolean aa(int[] huang,int a,int b){//是否已经存在
for(int i=0;i<b;i++){
if(a==huang[i] || (a-huang[i]==b-i) || (a-huang[i]==i-b)){
return false;
}
}
return true;
}
}
●基本介绍
java中允许同一个类中,多个同名方法的存在,但要求形参列表不一致!比如:System.out.println); out是PrintStream类型
●重载的好处
●快速入门案例
public class HelloWorld{
public static void main(String []args){
MyCalculator mc = new MyCalculator();
System.out.println(mc.calculate(1,2));
System.out.println(mc.calculate(1,2.1));
}
}
class MyCalculator {
//下面的四个calculate方法构成了重载
//两个整数的和
public int calculate(int n1, int n2){
return n1 +n2;
}
//一个整数,一个double的和
public double calculate(int n1,double n2) {
return n1 + n2;
}
//一个double ,一个工t和
public double calculate(double n1,int n2) {
return n1 + n2;
}
//三个int的和
public int calculate(int n1,int n2,int n3) {
return n1 + n2 + n2;
}
}
●注意事项和使用细节
●基本概念
java允许将同一个类中多个同名同功能但参数个数不同的方法,到装成一个方法。就可以通过可变参数实现
●基本语法
访问修饰符 返回类型 方法名(数据类型... 形参名){
}
●快速入门案例
public class HelloWorld{
public static void main(String []args){
HspMethod m = new HspMethod();
int sum=m.sum(1,5,100);
System.out.println(sum);
}
}
class HspMethod {
//1. int...表示接受的是可变参数,类型是int ,即可以接收多个1nt(0-多)
//2。使用可变参数时,可以当做数组来使用即nums可以当做数组
public int sum( int... nums){
System.out.println("接收的参数个数="+ nums. length);
int res = 0;
for(int i = 0; i < nums. length;i++){
res += nums[i];
}
return res;
}
}
●注意事项和使用细节
//细节:可变参数可以和普通类型的参数一起放在形参列表,但必须保证可变参数在最后
public void f2(String str,doubLe... nums) {
}
//细节:一个形参列表中只能出现一个可变参数//下面的写法是错的·
// public void f3(int. .. nums1,double. . . nums2) {}
●基本使用
面向对象中,变量作用域是非常重要知识点,相对来说不是特别好理解,要求深刻掌握变量作用域。
注意事项和细节使用
class Person {
String name = "jack";
public void say() {
//细节属性和局部变量可以重名,访问时遵循就近原则
String name= "king";
System.out. println( "say() name=" +name);
}
public void hi(){
String address ="北京";
// String address =“上海";//错误,重复定义变量
String name= "hsp";
}
}
●看一个需求
我们来看一个需求:前面我们在创建人类的对象时,是先把一个对象创建好后,再给他的年龄和姓名属性赋值,如果现在我要求,在创建人类的对象时,就直接指定这个对象的年龄和姓名,该怎么做?这时就可以使用构造器。
●基本语法
[修饰符] 方法名(形参列表){
方法体;
}
说明:
基本介绍
构造方法又叫构造器(constructor),是类的一种特殊的方法,它的主要作用是完成对新对象的初始化。它有几个特点:
快速入门
现在我们就用构造方法来完成刚才提出的问题:在创建人类的对象时,就直接指定这个对象的年龄和姓名
public class HelloWorld{
public static void main(String []args){
//当我们new 一个对象时,直接通过构造器指定名字和年龄
Person p1 = new Person( "smith",80);
System.out.println( "p1的信息如下");
System.out.println( "p1对象name=" + p1.name); // smith
System.out.println( "p1对象age=" + p1.age);//80
}
}
//在创建人类的对象时,就直接指定这个对象的年龄和姓名
//
class Person {
String name;
int age;
//构造器//老韩解读
//1。构造器没有返回值,也不能写void
//2。构造器的名称和类Person—样
//3.(String pName, int pAge)是构造器形参列表,规则和成员方法―样
public Person(String pName, int pAge){
System.out.println("构造器被调用~~完成对象的属性初始化");
name = pName;
age = pAge;
}
public Person(String pName){
System.out.println("构造器重载---");
name = pName;
}
}
●注意事项和使用细节
●先看一段代码,并分析问题
public class HelloWorld{
public static void main(String []args){
Dog dog1 = new Dog("大壮",3);
dog1.info();
}
}
class Dog{//类
String name;
int age;
// public Dog (String dName,int dAge){//构造器/ /name = dName;
//age = dAge;/ / }
//如果我们构造器的形参,能够直接写成属性名,就更好了
//但是出现了一个问题,根据变量的作用域原则
//构造器的name是局部变量,而不是属性
//构造器的age是局部变量,而不是属性
//==>引出this关键字来解决
public Dog (String name, int age){//构造器
name = name;
age = age;
}
public void info(){//成员方法,输出属性×信息
System.out.println(name + "\t" +age + "\t");
}
}
●什么是this
java虚拟机会给每个对象分配this,代表当前对象。
●使用this解决前面变量命名问题
public class HelloWorld{
public static void main(String []args){
Dog dog1 = new Dog("大壮",3);
dog1.info();
}
}
class Dog{//类
String name;
int age;
// public Dog (String dName,int dAge){//构造器/ /name = dName;
//age = dAge;/ / }
//如果我们构造器的形参,能够直接写成属性名,就更好了
//但是出现了一个问题,根据变量的作用域原则
//构造器的name是局部变量,而不是属性
//构造器的age是局部变量,而不是属性
//==>引出this关键字来解决
public Dog (String name, int age){//构造器
//this.name就是当前对象的属性name
this.name = name;
//this.age就是当前对象的属性age
this.age = age;
}
public void info(){//成员方法,输出属性×信息
System.out.println(name + "\t" +age + "\t");
}
}
this小结:简单的说,哪个对象调用,this就代表哪个对象
this的注意事项和使用细节
this关键字可以用来访问本类的属性、方法、构造器
this用于区分当前类的属性和局部变量
class Dog{//类
String name;
int age;
public Dog (String name, int age){//构造器
//this.name就是当前对象的属性name
this.name = name;
//this.age就是当前对象的属性age
this.age = age;
}
}
访问成员方法的语法:this.方法名(参数列表);注意:访问构造器语法:this(参数列表);必须放置第一条语句
/*
细节:访问构造器语法:this(参数列表);
注意只能在构造器中使用(即只能在构造器中访问另外一个构造器)
注意:访问构造器语法:this(参数列表);必须放置第一条语句
*/
public T(){
this("jack",100);//这里去访问 T(String name,int age)
System.out.print1n("T()构造器");
}
public T(String name, int age) {
System.out.println("T(String name,int age)构造器");
}
访问构造器语法:this(参数列表);注意只能在构造器中使用5. this不能在类定义的外部使用,只能在类定义的方法中使用。
●this的课堂案例
定义Person类,里面有name、age属性,并提供compareTo比较方法,用于判断是否和另一个人相等,提供测试类TestPerson用于测试名字和年龄完全一样,就返回true,否则返回false
public class HelloWorld{
public static void main(String []args){
Person p1 =new Person( "mary" ,20);
Person p2 =new Person( "smith", 30);
System.out.println(p1.compareTo(p2));
}
}
class Person{//类
String name;
int age;
public Person(String name,int age){
this.name=name;
this.age=age;
}
public boolean compareTo(Person p){
return (this.name.equals(p.name)&& this.age==p.age);
}
}
总的来说,我对ruby还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用
在控制台中反复尝试之后,我想到了这种方法,可以按发生日期对类似activerecord的(Mongoid)对象进行分组。我不确定这是完成此任务的最佳方法,但它确实有效。有没有人有更好的建议,或者这是一个很好的方法?#eventsisanarrayofactiverecord-likeobjectsthatincludeatimeattributeevents.map{|event|#converteventsarrayintoanarrayofhasheswiththedayofthemonthandtheevent{:number=>event.time.day,:event=>ev
我有一个表单,其中有很多字段取自数组(而不是模型或对象)。我如何验证这些字段的存在?solve_problem_pathdo|f|%>... 最佳答案 创建一个简单的类来包装请求参数并使用ActiveModel::Validations。#definedsomewhere,atthesimplest:require'ostruct'classSolvetrue#youcouldevencheckthesolutionwithavalidatorvalidatedoerrors.add(:base,"WRONG!!!")unlesss
好的,所以我的目标是轻松地将一些数据保存到磁盘以备后用。您如何简单地写入然后读取一个对象?所以如果我有一个简单的类classCattr_accessor:a,:bdefinitialize(a,b)@a,@b=a,bendend所以如果我从中非常快地制作一个objobj=C.new("foo","bar")#justgaveitsomerandomvalues然后我可以把它变成一个kindaidstring=obj.to_s#whichreturns""我终于可以将此字符串打印到文件或其他内容中。我的问题是,我该如何再次将这个id变回一个对象?我知道我可以自己挑选信息并制作一个接受该信
如果您尝试在Ruby中的nil对象上调用方法,则会出现NoMethodError异常并显示消息:"undefinedmethod‘...’fornil:NilClass"然而,有一个tryRails中的方法,如果它被发送到一个nil对象,它只返回nil:require'rubygems'require'active_support/all'nil.try(:nonexisting_method)#noNoMethodErrorexceptionanymore那么try如何在内部工作以防止该异常? 最佳答案 像Ruby中的所有其他对象
我在Rails工作并有以下类(class):classPlayer当我运行时bundleexecrailsconsole然后尝试:a=Player.new("me",5.0,"UCLA")我回来了:=>#我不知道为什么Player对象不会在这里初始化。关于可能导致此问题的操作/解释的任何建议?谢谢,马里奥格 最佳答案 havenoideawhythePlayerobjectwouldn'tbeinitializedhere它没有初始化很简单,因为你还没有初始化它!您已经覆盖了ActiveRecord::Base初始化方法,但您没有调
我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/
我有一个服务模型/表及其注册表。在表单中,我几乎拥有服务的所有字段,但我想在验证服务对象之前自动设置其中一些值。示例:--服务Controller#创建Action:defcreate@service=Service.new@service_form=ServiceFormObject.new(@service)@service_form.validate(params[:service_form_object])and@service_form.saverespond_with(@service_form,location:admin_services_path)end在验证@ser
我想让一个yaml对象引用另一个,如下所示:intro:"Hello,dearuser."registration:$introThanksforregistering!new_message:$introYouhaveanewmessage!上面的语法只是它如何工作的一个例子(这也是它在thiscpanmodule中的工作方式。)我正在使用标准的rubyyaml解析器。这可能吗? 最佳答案 一些yaml对象确实引用了其他对象:irb>require'yaml'#=>trueirb>str="hello"#=>"hello"ir
假设我有一个FireNinja我的数据库中的对象,使用单表继承存储。后来才知道他真的是WaterNinja.将他更改为不同的子类的最干净的方法是什么?更好的是,我很想创建一个新的WaterNinja对象并替换旧的FireNinja在数据库中,保留ID。编辑我知道如何创建新的WaterNinja来self现有FireNinja的对象,我也知道我可以删除旧的并保存新的。我想做的是改变现有项目的类别。我是通过创建一个新对象并执行一些ActiveRecord魔法来替换行,还是通过对对象本身做一些疯狂的事情,或者甚至通过删除它并使用相同的ID重新插入来做到这一点,这是问题的一部分。