关于封装,满足几个原则,一般的成员变量用privat修饰,仅暴露少量方法获取,如果是内部的操作方法也用private,除非是希望被全局使用,的才考虑用public,如果是进希望被子类用的话可以考虑用protected。
.如果在文件里面有包的话,在cmd中一定不要省略-d选项,如果省略则不会生成对应的包的文件;
.在Java 包机制里面必须有两方面保证:源文件里使用package语句指定包名,class文件必须放在对应的路径下;一个源文件只能指定一个包,在同一个包下面的一般情况下可以自由访问,但是如果是父包和子包的关系,父包的类用子包的,那么必须使用子包的全名;某个包要用其他包中的类时,就要用该包的全名,一个源文件可以用多个import来导入其他包的类,.关于import,如果用import加上包*则表示该包下的所有类,而不表示它的子包下面的类,如果要用则的引用子包;
关于在Java文件里面所有源文件默认导入java.lang包下的所有类;因此使用String,System类时都无需使用import语句来导入这些类,至于Arrays类,位于java.until包下,则必须用import导入;如果导入的两个包的类都含有同一个方法,则会系统报错,这时只能用原始方法;静态导入:import static加指定包中的类表示导入了某个类的全部静态变量,方法;同时静态导入和普通导入没有顺序而言,但是这些都一定在package后面,类定义之前;
关于构造器的小知识:在创建对象时,系统先为对象分配内存空间,并为其默认初始化;然后再对对象进行构造器里面的操作,最后返回给对象一个引用类型的值,让外部程序可以访问这个对象;
再次总结关于this的用法:
1.当一个类的属性(成员变量)名与访问该属性的方法参数名相同时,则需要使用 this 关键字来访问类中的属性,以区分类的属性和方法中的参数;包括构造器;
2.在一个类里面,可以在一个方法里面调用另一个该类方法用this.方法的形式,this可以省略;但是在static方法里面不可以用this,;
3.关于构造器的应用;如果有两个构造器,其中一个构造器想要完全用到第一个构造器的功能这时候可以用this调用格式为:this(...),...为1被调用的构造器的参数;必须在构造器里第一句话;
继承:子类可以获得父类的很多东西,但是除了构造器和初始化块;每一个类都只能有一个直接父类;(这里是在一个包下面的代码)
package xiaosi;
public class Person
{
public double weight;
public void info()
{
System.out.println("我是一个水果,重:"+weight+"g");
}
}
class Apple extends Person
{
public static void main(String[]args)
{
Apple a=new Apple();
a.weight=56;
a.info();
}
}
我是一个水果,重:56.0g
如果一个类没有显示指定某个类是他的直接父类,默认java.lang.Object类是它的父类,java.lang.Object是所有类的父类,可以是直接父类也可以是间接父类;子类可以重写父类方法,但是,如果要重写的话,必须遵循两同两小一大的规则;方法名和形参列表相同;“两小”指的是返回值类型和异常类子类比父类更小,而且要么都是类方法,要么都是实例方法:这样是对的:
//注,这里是在xiaosi包里,是在Person.java的文件里;
package xiaosi;
public class Person
{
public void fly()
{
System.out.println("我在天空自由自在的飞翔");
}
}
class Tuoniao extends Person
{
public void fly()
{
System.out.println("我只能在地上奔跑");
}
public static void main(String[]args)
{
Tuoniao os=new Tuoniao();
os.fly();
}
}
这样会报错:
package xiaosi;
public class Person
{
public static void test()
{
}
}
class person extends Person
{
public void test()
{
}
}
当子类把父类的方法覆盖了之后,子类的对象将无法访问父类中被父类覆盖的对象,但可以在,子类方法中调用父类被覆盖的方法;用super或者父类名对应的是实例方法和类方法,如果在父类里面方法是由private修饰的话,子类不可以访问且重写,但是子类也可以写一个private型的那也不是重写,而是定义了一个新方法;
package xiaosi;
public class Person
{
private static void test()
{
}
}
class person extends Person
{
static void test()
{
}
public static void main(String[]args)
{
}
}
当然,这里并不是由于上述原因,而是因为子类的名字问题,不知道为什么取文件名的小写就会报错,所以尽量避免:
package xiaosi;
public class Person
{
int weight;
private static void test()
{
System.out.println(" ");
}
}
class xiao extends Person
{
static void test()
{
}
public static void main(String[]args)
{
}
}
改成这样就可以了,其实下面的方法就不是重写,所以什么修饰词都可以;super在static方法里面不可以用
关于父类和子类,在一个继承了父类的子类创建一个对象时,系统不仅会为该类中的实例变量,还会为它的所有父类直接或者间接父类的实力分配空间,就算重名也会分配;
super不仅可以调用父类的变量方法,还可以在自己的构造器里的调用父类的构造器,并且不可以和this同时存在,因为两个都应在构造器的第一行;
class Base
{
public double size;
public String name;
public Base(double size,String name)
{
this.name=name;
this.size=size;
}
}
public class Main extends Base
{
public String color;
public Main(double size,String name,String color)
{
super(size,name);
this.color=color;
}
public static void main(String[]args)
{
Main s=new Main(5.6,"测试对象","红色");
{
System.out.println(s.size+"---"+s.name+"--"+s.color);
}
}
}
运行结果:
5.6---测试对象--红色
关于子父类构造器:
1.如果子构造器第一行有super,将根据传入的参数调用父类的构造器;
2.如果只有this那么就是用该类里面的构造器先来构造这个构造器,然后那个被调用的就是先用父类的默认构造器;
3.如果都没有,那就是也会先调用父类默认无参数构造器;
总的来说,不管哪种情况都会调用父类构造器;也就是说,创造任何对象,最先执行的总是java.lang.Object类的构造器;
用代码显示一下构造器的运行流程:
class Creature
{
public Creature()
{
System.out.println("无参数的构造器");
}
}
class Animal extends Creature
{
public Animal(String name)
{
System.out.println("带一个参数的构造器,该动物为"+name);
}
public Animal(String name,int age)
{
System.out.println("带两个参数的构造器,该动物为"+name+"年龄为"+age);
}
}
class Wolf extends Animal
{
public Wolf()
{
super("灰太狼",3);
System.out.println("Wolf无参数构造器");
}
public static void main(String[]args)
{
new Wolf();
}
}
多态: java允许将子类对象直接付给父类引用变量;从而形成了多态;当多态的时候,方法是按照父类来的,(但是子类和父类相同的方法会被子类覆盖),而且实例变量不具有多态性,用的是父类的;
class Baseclass
{
public int book=6;
public void base()
{
System.out.println("父类的普通方法");
}
public void test()
{
System.out.println("父类被覆盖的方法");
}
}
public class Main extends Baseclass
{
public String book="轻量级Java EE企业应用实战";
public void test()
{
System.out.println("子类覆盖父类的方法");
}
public void sub()
{
System.out.println("子类的普通方法");
}
public static void main(String[]args)
{
Baseclass bc=new Baseclass();
System.out.println(bc.book);
bc.test();
bc.base();
Main sc=new Main();
System.out.println(sc.book);
sc.test();
sc.sub();
Baseclass pl=new Main();
// pl.sub();
pl.test();
pl.base();
System.out.println(pl.book);
}
}
6
父类被覆盖的方法
父类的普通方法
轻量级Java EE企业应用实战
子类覆盖父类的方法
子类的普通方法
子类覆盖父类的方法
父类的普通方法
6
关于强制类型转换符:数值类型不可以和布尔类型相互转换,没有继承关系的引用类型也不可以相互转换,如果试图把一个父类类型转换成子类类型,则该父类类型必须实际上是子类类型;
public class Main
{
public static void main(String[]args)
{
double d=13.4;
long l=(long)d;
System.out.println(l);
int in=5;
//boolean b=(boolean)in;//编译出错;
Object obj="hello";
String objStr=(String)obj;//Object是所有类的父类;
System.out.println(objStr);
//定义一个编译时类型为Object,运行时为Integer
Object objPri=Integer.valueOf(5);
String str=(String)objPri;
}
}
所以最后一个转化有问题:
instanceof运算符可以判断是否可以转换,双目运算符;虽然可以判断,但是前编译时后类型要么有父子继承关系,要么就是相同;
举例:
public class Main
{
public static void main(String[]args)
{
Object hello="hello";
System.out.println("字符串是否是Object类的实例"+(hello instanceof Object));
System.out.println("字符串是否是String类的实例:"+(hello instanceof String));
System.out.println("字符串是否是Math类的实例"+(hello instanceof Math));
System.out.println("字符串是否是Comparable接口的实例"+(hello instanceof Comparable));
String a="HELLO";
// System.out.println("字符串是否是Math类的实例"+(a instanceof Math));没有继承关系编译无法通过
}
}
字符串是否是Object类的实例true
字符串是否是String类的实例:true
字符串是否是Math类的实例false
字符串是否是Comparable接口的实例true
字符串是否是Math类的实例
20.继承和组合:
组合实例:
class Animal
{
private void beat()
{
System.out.println("心脏跳动");
}
public void breathe()
{
beat();
System.out.println("吸一口气,吐一口气,呼吸中");
}
}
class Bird
{
private Animal a;
public Bird (Animal a)
{
this.a=a;
}
public void breathe()
{
a.breathe();
}
public void fly()
{
System.out.println("我在天空自由自在的翱翔");
}
}
class Wolf
{
private Animal a;
public Wolf(Animal a)
{
this.a=a;
}
public void breathe()
{
a.breathe();
}
public void run()
{
System.out.println("我在草地上奔跑");
}
}
public class Main
{
public static void main(String[]aegs)
{
Animal a1=new Animal();
Bird b=new Bird(a1);
b.breathe();
b.fly();
Animal a2=new Animal();
Wolf b2=new Wolf(a2);
b2.breathe();
b2.run();
}
}
组合和继承,比如有一个模板类,如果要球创建的类是这个模板类的特殊一部分,则用继承比如,水果和苹果,比如上面这个就适合用继承,而当要创建的新类是这个类的一部分则用组合,比如胳膊和人;
初始化块:在创建对象之前,会先初始化类,这时候会从顶层父类开始一直执行类初始化代码;知道该类的类初始化代码,然后再按照这个顺序执行实例代码块,如果这中间有实例的声明代码,那么就按顺序执行;所以可以看见,刚开始第一次创建对象的时候执行了,类初始化代码被执行了,但是后面第二次就没有;
class Root
{
static
{
System.out.println("Root类的初始化");
}
{
System.out.println("Root的实例初始化块");
}
public Root()
{
System.out.println("Root的无参数构造器");
}
}
class Mid extends Root
{
static
{
System.out.println("Mid的类的初始化块");
}
{
System.out.println("Mid的实例初始化块");
}
public Mid()
{
System.out.println("Mid的无参数构造器");
}
public Mid (String msg)
{
this();
System.out.println("Mid的带参构造器,其参数值为"+msg);
}
}
class Leaf extends Mid
{
static
{
System.out.println("Leaf的类初始化");
}
{
System.out.println("Leaf的实例初始化");
}
public Leaf()
{
super("疯狂Java讲义");
System.out.println("执行Leaf的构造器");
}
}
public class Main
{
public static void main(String[]args)
{
new Leaf();
new Leaf();
}
}
运行结果:
Root类的初始化
Mid的类的初始化块
Leaf的类初始化
Root的实例初始化块
Root的无参数构造器
Mid的实例初始化块
Mid的无参数构造器
Mid的带参构造器,其参数值为疯狂Java讲义
Leaf的实例初始化
执行Leaf的构造器
Root的实例初始化块
Root的无参数构造器
Mid的实例初始化块
Mid的无参数构造器
Mid的带参构造器,其参数值为疯狂Java讲义
Leaf的实例初始化
执行Leaf的构造器
包装类,系统为基本数据类型提供了,自动装箱和自动拆箱;即基本类型可以直接转换成引用类型:
public class Main
{
public static void main(String[]args)
{
Integer inObj=5;
Object boolObj=true;
int it=inObj;
if(boolObj instanceof Boolean)
{
boolean b=(Boolean)boolObj;
System.out.println(b);
}
}
}
字符串类型也可以转化成基本类型:通过String.valueOf()也可以从基本类型转变成字符串类型;
public class Main
{
public static void main(String[]args)
{
String intSr="123";
int it1=Integer.parseInt(intSr);
int it2=Integer.valueOf(intSr);
System.out.println(it1+"--"+it2);
String floatSr="4.56";
float f1=Float.parseFloat(floatSr);
float f2=Float.valueOf(floatSr);
System.out.println(f1+"--"+f2);
}
}
比较两个变量是否相等,==和equals
public class Main
{
public static void main(String[]args)
{
int it=65;
float f1=65.0f;
System.out.println("65和65.0f是否相等?"+(it==f1));
char ch='A';
System.out.println("65和A是否相等?"+(it==ch));
String str1=new String("hello");
String str2=new String("hello");
System.out.println("两个字符串是否相等"+(str1==str2));
System.out.println("两个字符串是否equal"+(str1.equals(str2)));
}
}
结果:
65和65.0f是否相等?true
65和A是否相等?true
两个字符串是否相等false
两个字符串是否equaltrue
final关键字:修饰变量不可以被再次赋值,修饰方法不可以被重写,可以被重载,修饰类不可以被继承,为最终类,比如String类;
抽象类:父类没有实现,子类必须实现(可以为空,但是不可以没有),抽象方法必须在抽象类里面;抽象类不能实例化不可以用new来创建对象,也就是只能用子类调用;抽象类为子类提供抽象的规范模板
abstract class Main
{
public abstract void dog();
}
class Dog extends Main
{
public void dog()
{
System.out.println("往往");
}
}
如果去掉上面dog方法的中括号以及中括号里的内容,则会报错;
接口类型:比抽象类还要抽象,只定义规范,没有具体实现,接口可以多继承,接口里面定义的都是public static final常量,都是public abstract 修饰的方法,可以不写,系统会默认认为;要使用必须使用实现类,实现类用implements,方法格式和继承差不多,可以实现多个接口,不可以用接口类型创建对象;
public interface InterTest
{
int MAXHIDE=9;
void fly();
}
interface Care
{
void courage();
}
class Angel implements InterTest,Care
{
@Override
public void fly() {
System.out.println("我在自由自在的飞行");
}
@Override
public void courage() {
System.out.println("我很勇敢的");
}
}
class Testlala
{
public static void main(String[]args)
{
InterTest a=new Angel();
a.fly();
}
}
内部类:
成员内部类:静态内部类和非静态内部类,静态内部类就是在类里面的类有static修饰,而非静态内部类就是没有static修饰;非静态内部类可以访问外部类的成员变量采用外部类名.this.成员变量名;但是外部类不可以直接访问非静态内部类成员变量:非静态内部类不可以有静态方法和静态变量;
class Outer
{
private int age=34;
class Inter
{
int m;
public void fly()
{
System.out.println(Outer.this.age);
}
}
}
class Ha
{
public static void main(String[]args)
{
Outer.Inter w=new Outer().new Inter();//非静态内部类访问需要靠外部类对象
w.fly();
}
}
打印结果为:34
静态内部类访问就不需要靠外部对象可以将上述代码main函数里面改为:
public static void main(String[]args)
{
Outer.Inter w=new Outer.Inter();
w.fly();
}
匿名内部类:适合只使用一次的类:
/**
* 匿名内部类的测试
*/
interface A
{
void aa();
}
class pA
{
public static void amm(A al)
{
System.out.println("hhhh");
al.aa();
}
public static void main(String[]args)
{
pA.amm(new A()
{
@Override
public void aa()
{
System.out.println("我真帅");
}
}
);
}
}
局部内部类:方法里面定义的内部类;作用于仅限于与该方法;
String类的详解:
String 直接用字符串定义一个变量会放在字符串常量池,此时它们指的是同一个对象
class stringTest
{
public static void main(String[]args)
{
String a1="小饺子";
String a2="小饺子";
String a3=new String("小饺子");
System.out.println("a1是否==a2"+(a1==a2));//里面的括号一定要打上
System.out.println("a1是否==a3"+(a1==a3));
}
}
/*
运行结果:
a1是否==a2true
a1是否==a3false
*/
常用的String用法:
class stringTest
{
public static void main(String[]args)
{
String a1="小饺子";
String a2="小饺子";
String a3=new String("小饺子");
System.out.println("a1是否==a2"+(a1==a2));//里面的括号一定要打上
System.out.println("a1是否==a3"+(a1==a3));//ctrl+?注释;
System.out.println(a3.charAt(1));//返回索引的第几个值;
System.out.println(a1.length());//返回字符串的长度
System.out.println(a1.equalsIgnoreCase(a2));//把字符串所有小写字母转为大写字母
System.out.println(a1.indexOf(a2));//返回字符串出现的第一次的第一个字符的索引,如果没有则返回-1;
System.out.println(a1.replace("小","Abc"));//将字符串中第一个参数替换为第二个参数’
System.out.println(a1.startsWith("小"));//判断字符串是否以参数开头
System.out.println(a1.endsWith("子"));//是否以参数结尾
System.out.println(a1.substring(2));//提取字符串中参数开始的索引到结尾的字符串构成新的对象
System.out.println(a2.substring(1));
System.out.println(a1.toLowerCase());//将字符串转换为小写
System.out.println(a1.toUpperCase());//转为大写
System.out.println(a1.trim());//删除字符穿开头和结尾的空格然后创建新的对象;
//注:上面的都是创建新的字符串并没有动原来的字符串;
}
}
运行结果:
a1是否==a2true
a1是否==a3false
饺
3
true
0
Abc饺子
true
true
子
饺子
小饺子
小饺子
小饺子
Arrays工具类:
class ArraysTest
{
public static void main(String[]args)
{
int []a=new int[]{1,4,3,1,5};
System.out.println(Arrays.toString(a));//打印数组内容
Arrays.sort(a);//对数组排序
System.out.println(Arrays.toString(a));
System.out.println(Arrays.binarySearch(a,1));//对数组进行二分查找
}
}
写题总结:
C-Bargaining Table暑假第一周任务 - Virtual Judge (vjudge.net)
写的最久的一个题,到最后还是暴力出奇迹,由于数据较小,我直接用六个嵌入循环,直接先用四个循环找矩形的左上和右下,然后再用两个循环判断矩形关键是否都是0,如果有1,直接结束里面两个循环;然后再继续确定左上和右下,其实本来想的是这时候还可以将右下y坐标直接结束的,倒数第三层往下还是会包括那个一,但是奈何太水,没来得及实现暴力过了,动态规划实在没想出来QAQ;
#include<stdio.h>
char a[30][30];
int main()
{
int n,m;//注意这里没有间隔符,需要有间隔符,所以先把它当作字符算;
scanf("%d %d",&n,&m);
for(int i=1; i<=n; i++)
scanf("%s",a[i]+1);
int maxx=0;
int flag=0;
int I,J;
int h=0,mx,my,mi,mj;
int hc,lc;
//被这个前缀和给搞疯掉
for(int i=1; i<=n; i++)
{
for(int j=1; j<=m; j++)
{
for( hc=i; hc<=n; hc++)
{
for( lc=j; lc<=m; lc++)
{
for( I=i; I<=hc; I++)
{
for(J=j; J<=lc; J++)
{
if(a[I][J]!='0')
{
flag=1;
break;
}
}
if(flag==1)
{
flag=0;
break;
}
}
if(I==hc+1&&J==lc+1)
{
h=2*((hc-i+1)+(lc-j+1));
if(h>maxx)maxx=h;
}
}
}
}
}
printf("%d",maxx);
return 0;
}
这题唯一要注意的是,刚开始的时候输入的数字没有空格,所以不可以当作整数输入,如果把它当作一维数组的字符串输的话,如果你习惯以1作为起始位置,一定要记得加一;
D-Coins)
这是一个递归题,而且时间要求也不高,就可以直接用一个函数找自己的因子就可以了:
#include<stdio.h>
int coin(int n)
{
if(n==1)return 1;
int h;
for(int i=n-1;i>=1;i--)
{
if(n%i==0){h=i;printf("%d ",i);break;}
}
return coin(h);
}
int main()
{
int n;
scanf("%d",&n);
printf("%d ",n);
coin(n);
}
E-Sale
题目问的是这个人能赚多少,不可以赚就不买呗,所以最少是0元,最多就是求负数有多少个:从小到大排序,然后找到等于零或者开始小于零就不找了,当然如果m足够大的话,如果m的数量比负数的少,就取前m个,然后加起来取相反数;
#include<bits/stdc++.h>
using namespace std;
int a[100];
int main()
{
int n,m;
scanf("%d %d",&n,&m);
for(int i=0;i<n;i++)
{
scanf("%d",&a[i]);
}
sort(a,a+n);
int h=0;
for(int i=0;i<m;i++)
{
if(a[i]<=0)
h+=-a[i];
else break;
}
printf("%d",h);
return 0;
}
F-Forbidden Integer)
这题目想的确实有点久了,刚开始一直想有什么规律没,然后不停在除数余数上面徘徊,就在昨晚突然就灵机一动,只要有一不就都可以不,然后仔细看了看下面的注解,是有其他答案,但是如果除去1的话,又该怎么算这个规律呢?然后想到2是所有偶数的万能,可是如果是奇数,那就没办法了,但是,如果有一个三呢,最后总结下来2,3凑一起是万能的 ,然后就可以分下面几种情况:
如果这个出去的数里面是1的话,所有的都可以用以代替,数量为n,如果是1的话,如果k<2就一定不可以,如果大于等于二,如果是偶数,是可以的,则都用2代替,数量为n/2;如果是奇数,而且k大于三的话那么都可以用n/2这时候多了一个1,可以去掉一个二,然后在这个2上加一变成三,也就是2的数量变为n/2-1,后面还有一个3,此时总共还是有n/2个数,如果是奇数k=2的话,由于这时候x=1,也就是除去了1,所以一定是no;
#include<stdio.h>
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n,k,x;
int h=0;
scanf("%d %d %d",&n,&k,&x);
if(x!=1)
{
printf("YES\n");
printf("%d\n",n);
for(int i=1; i<=n; i++)
{
printf("1 ");
}
printf("\n");
}
else
{
if(k>=2)
{
if(n%2!=0)
{
if(k>=3)
{
printf("YES\n");
printf("%d\n",n/2);
for(int i=0; i<n/2-1; i++)
printf("2 ");
printf("3 ");
printf("\n");
}
else
{
printf("NO\n");
}
}
else
{
printf("YES\n");
printf("%d\n",n/2);
for(int i=0;i<n/2;i++)
{
printf("2 ");
}
printf("\n");
}
}
else printf("NO\n");
}
}
return 0;
}
最最最后,喝下一碗心灵鸡汤准备睡觉咯:愿你在被打击时,记起你的珍贵,抵抗恶意;愿你在迷茫时,坚信你的珍贵;爱你所爱,行你所行,听从你心,无问西东。