Java中一个只实现了接口的类,在它的构造方法中调用了super()方法,这样做有什么意义呢 1C

今天在看spring源码spring-core包中的EncodedResource.java时发现它的其中一个构造方法里出现了:
private EncodedResource(Resource resource, String encoding, Charset charset) {
super();
Assert.notNull(resource, "Resource must not be null");
this.resource = resource;
this.encoding = encoding;
this.charset = charset;
}
一开始并不知道super()到底做了什么,后来经别人提醒知道了原来这是在调用Object类的
的构造方法,这样是对的吗?还有,这样做有什么意义吗?

6个回答

写不写无所谓,子类构造方法第一行默认是调用父类的无参构造方法的,这里只是显式的将其写出来了。但是调用父类有参构造器时,必须显式的写出super(xxx)。
此处super()无意义,只是将省略的东西,写出来而已。

如果不写构造方法,默认会提供一个无参构造方法,手写重载构造方法,必须第一行调用super,对于这个语法现象的理解我觉得 是在做类的内存初始化时(比如new)需要先初始他父类的方法和属性

stevenjeff
天津老张 你调用的本类含参的构造方法第一行是super,就是调用父类的构造方法,如果你不写任何构造方法,编译器默认会加上一个无参构造方法,这个方法的第一行就是调用super,Object方法有很多所有对象的公用方法,比如toString,hashCode,equals等,还有线程相关的wait,notify等,而且很多方法你看源码都是native的,也就是实际使用C写的实现
3 年多之前 回复
death05
death05 我这个EncodedResource类,在实例化它的时候调用了自己的含参构造函数,已经不可能去调用EncodedResource类的默认无参构造方法了吧?而且,为什么会需要初始化object类的方法和属性呢?这个EncodedResource类父类应该只有Object类了
3 年多之前 回复

此处附上源代码:
EncodedResource.java
/*

  • Copyright 2002-2016 the original author or authors. *
  • Licensed under the Apache License, Version 2.0 (the "License");
  • you may not use this file except in compliance with the License.
  • You may obtain a copy of the License at *
  • http://www.apache.org/licenses/LICENSE-2.0 *
  • Unless required by applicable law or agreed to in writing, software
  • distributed under the License is distributed on an "AS IS" BASIS,
  • WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  • See the License for the specific language governing permissions and
  • limitations under the License. */

package org.springframework.core.io.support;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.nio.charset.Charset;

import org.springframework.core.io.InputStreamSource;
import org.springframework.core.io.Resource;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;

/**

  • Holder that combines a {@link Resource} descriptor with a specific encoding
  • or {@code Charset} to be used for reading from the resource. *
  • Used as an argument for operations that support reading content with

  • a specific encoding, typically via a {@code java.io.Reader}. *
  • @author Juergen Hoeller
  • @author Sam Brannen
  • @since 1.2.6
  • @see java.io.Reader
  • @see java.nio.charset.Charset
    */
    public class EncodedResource implements InputStreamSource {

    private final Resource resource;

    private final String encoding;

    private final Charset charset;

    /**

    • Create a new {@code EncodedResource} for the given {@code Resource},
    • not specifying an explicit encoding or {@code Charset}.
    • @param resource the {@code Resource} to hold (never {@code null}) */ public EncodedResource(Resource resource) { this(resource, null, null); }

    /**

    • Create a new {@code EncodedResource} for the given {@code Resource},
    • using the specified {@code encoding}.
    • @param resource the {@code Resource} to hold (never {@code null})
    • @param encoding the encoding to use for reading from the resource */ public EncodedResource(Resource resource, String encoding) { this(resource, encoding, null); }

    /**

    • Create a new {@code EncodedResource} for the given {@code Resource},
    • using the specified {@code Charset}.
    • @param resource the {@code Resource} to hold (never {@code null})
    • @param charset the {@code Charset} to use for reading from the resource */ public EncodedResource(Resource resource, Charset charset) { this(resource, null, charset); }

    private EncodedResource(Resource resource, String encoding, Charset charset) {
    super();
    Assert.notNull(resource, "Resource must not be null");
    this.resource = resource;
    this.encoding = encoding;
    this.charset = charset;
    }

    /**

    • Return the {@code Resource} held by this {@code EncodedResource}. */ public final Resource getResource() { return this.resource; }

    /**

    • Return the encoding to use for reading from the {@linkplain #getResource() resource},
    • or {@code null} if none specified. */ public final String getEncoding() { return this.encoding; }

    /**

    • Return the {@code Charset} to use for reading from the {@linkplain #getResource() resource},
    • or {@code null} if none specified. */ public final Charset getCharset() { return this.charset; }

    /**

    • Determine whether a {@link Reader} is required as opposed to an {@link InputStream},
    • i.e. whether an {@linkplain #getEncoding() encoding} or a {@link #getCharset() Charset}
    • has been specified.
    • @see #getReader()
    • @see #getInputStream() */ public boolean requiresReader() { return (this.encoding != null || this.charset != null); }

    /**

    • Open a {@code java.io.Reader} for the specified resource, using the specified
    • {@link #getCharset() Charset} or {@linkplain #getEncoding() encoding}
    • (if any).
    • @throws IOException if opening the Reader failed
    • @see #requiresReader()
    • @see #getInputStream() */ public Reader getReader() throws IOException { if (this.charset != null) { return new InputStreamReader(this.resource.getInputStream(), this.charset); } else if (this.encoding != null) { return new InputStreamReader(this.resource.getInputStream(), this.encoding); } else { return new InputStreamReader(this.resource.getInputStream()); } }

    /**

    • Open a {@code java.io.InputStream} for the specified resource, ignoring any
    • specified {@link #getCharset() Charset} or {@linkplain #getEncoding() encoding}.
    • @throws IOException if opening the InputStream failed
    • @see #requiresReader()
    • @see #getReader() */ @Override public InputStream getInputStream() throws IOException { return this.resource.getInputStream(); }

    @Override
    public boolean equals(Object other) {
    if (this == other) {
    return true;
    }
    if (!(other instanceof EncodedResource)) {
    return false;
    }
    EncodedResource otherResource = (EncodedResource) other;
    return (this.resource.equals(otherResource.resource) &&
    ObjectUtils.nullSafeEquals(this.charset, otherResource.charset) &&
    ObjectUtils.nullSafeEquals(this.encoding, otherResource.encoding));
    }

    @Override
    public int hashCode() {
    return this.resource.hashCode();
    }

    @Override
    public String toString() {
    return this.resource.toString();
    }

}

InputStreamSource.java
/*

  • Copyright 2002-2012 the original author or authors. *
  • Licensed under the Apache License, Version 2.0 (the "License");
  • you may not use this file except in compliance with the License.
  • You may obtain a copy of the License at *
  • http://www.apache.org/licenses/LICENSE-2.0 *
  • Unless required by applicable law or agreed to in writing, software
  • distributed under the License is distributed on an "AS IS" BASIS,
  • WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  • See the License for the specific language governing permissions and
  • limitations under the License. */

package org.springframework.core.io;

import java.io.IOException;
import java.io.InputStream;

/**

  • Simple interface for objects that are sources for an {@link InputStream}. *
  • This is the base interface for Spring's more extensive {@link Resource} interface. *

  • For single-use streams, {@link InputStreamResource} can be used for any

  • given {@code InputStream}. Spring's {@link ByteArrayResource} or any
  • file-based {@code Resource} implementation can be used as a concrete
  • instance, allowing one to read the underlying content stream multiple times.
  • This makes this interface useful as an abstract content source for mail
  • attachments, for example. *
  • @author Juergen Hoeller
  • @since 20.01.2004
  • @see java.io.InputStream
  • @see Resource
  • @see InputStreamResource
  • @see ByteArrayResource
    */
    public interface InputStreamSource {

    /**

    • Return an {@link InputStream}.
    • It is expected that each call creates a fresh stream.

    • This requirement is particularly important when you consider an API such

    • as JavaMail, which needs to be able to read the stream multiple times when
    • creating mail attachments. For such a use case, it is required
    • that each {@code getInputStream()} call returns a fresh stream.
    • @return the input stream for the underlying resource (must not be {@code null})
    • @throws IOException if the stream could not be opened
    • @see org.springframework.mail.javamail.MimeMessageHelper#addAttachment(String, InputStreamSource) */ InputStream getInputStream() throws IOException;

}

所有类的父类为Object 当你实例化的时候,在调用该类的构造方法的时候,首先都会调用父类的构造方法。
super。调用父类的构造方法。也可以调用父类的方法

qq_34926048
暴走的小白菜 这个是java语法自带的,可以去掉的。但是当你继承别的类的时候,这个super就必须带上了。
3 年多之前 回复
death05
death05 为什么这边要特意调用一下Object类的构造方法呢
3 年多之前 回复

不写也是可以的,你可以试一试去掉super,

:这是这个类的有参构造函数,调用父类的构造函数,而且这是java语法规定,父类定义了构造函数,那么子类的构造函数的第一句代码必须是super()的。
Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
其他相关推荐
java中panel实现线程接口以后,要调用repaint函数时,不进run函数
具体情况是 mypanel类实现了线程接口,在run函数中定义了sleep(100)后调用repaint函数,做一个小坦克游戏,在repaint之前要判断是否击中坦克,击中后要显示三张图片来体现爆炸效果,可是经过调试发现,每次第一次击中的时候,都是直接好多次repaint,没有休眠,后来发现根本就没有进mypanel的run()方法,好像有另一个其他线程再调用paint。这是怎么回事?感谢大家了 package com.TankGame; import java.awt.*; import java.util.*; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import javax.swing.*; public class MyTankGame1 extends JFrame{ public static void main(String[] args) { // TODO Auto-generated method stub MyTankGame1 tankgame = new MyTankGame1(); } //构造函数 public MyTankGame1(){ MyPanel mp = new MyPanel(); //启动mp线程 Thread t = new Thread(mp); t.start(); this.add(mp); this.addKeyListener(mp); this.setIconImage(new ImageIcon("TankImage/TANK.jpg").getImage()); this.setTitle("坦克大战"); this.setLocation(350, 100); this.setSize(500, 400); this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); this.setVisible(true); } } //我的面板类 class MyPanel extends JPanel implements KeyListener,Runnable{ //定义一个玩家的坦克 MyTank mytank = null; Vector<EnemyTank> ets= new Vector<EnemyTank>(); //定义爆炸效果集合 Vector<Boom> boom = new Vector<Boom>(); int enSize = 8; //定义三张图片,三张图片组成一次爆炸 Image image1 = null; Image image2 = null; Image image3 = null; //构造函数 public MyPanel(){ mytank = new MyTank(100,250); mytank.setType(0); for(int i=0;i<enSize;i++){ EnemyTank et = new EnemyTank((i+1)*50,0); et.setType(1); et.setDirect(1); et.setType(1); ets.add(et); } //初始化图片 image1 = Toolkit.getDefaultToolkit().getImage(Panel.class.getResource("/1.jpg")); image2 = Toolkit.getDefaultToolkit().getImage(Panel.class.getResource("/2.jpg")); image3 = Toolkit.getDefaultToolkit().getImage(Panel.class.getResource("/3.jpg")); } public void hittank(Bullet b,EnemyTank et){ //判断该坦克的方向 switch(et.direct){ //方向朝上或者下 case 0: case 1: if(b.x>et.x&&b.x<et.x+20&&b.y>et.y&&b.y<et.y+30){ //击中 //子弹死亡 坦克死亡 b.isAlive=false; et.isLive=false; //创建一个爆炸效果,放入boom Boom bom = new Boom(et.x,et.y); boom.add(bom); } case 2: case 3: if(b.x>et.x-5&&b.x<et.x+25&&b.y>et.y+5&&b.y<et.y+25){ //击中 b.isAlive=false; et.isLive=false; Boom bom = new Boom(et.x,et.y); boom.add(bom); } } } //方向:上下左右,对应0123 public void paint(Graphics g){ super.paint(g); System.out.println("xx"); g.fillRect(0, 0, 500, 500); this.drawTank(this.mytank.getX(), this.mytank.getY(), g, this.mytank.getDirect(), this.mytank.getType() ); //从ss中画出所有子弹 for(int i=0;i<this.mytank.ss.size();i++){ Bullet b = mytank.ss.get(i); if(b!=null&&b.isAlive==true){ g.drawRect(b.x, b.y, 1, 1); } if(b.isAlive==false){ //从ss中删掉该子弹 mytank.ss.remove(b); } } for(int i=0;i<ets.size();i++){ EnemyTank et = ets.get(i); if(et.isLive){ this.drawTank(et.getX(), et.getY(), g, et.getDirect(), et.getType()); } } //画出爆炸 System.out.println(boom.size()); for(int j=0;j<boom.size();j++){ Boom bom = boom.get(j); if(bom.life>6){ g.drawImage(image1, bom.x, bom.y, 30, 30, this); }else if(bom.life>3){ g.drawImage(image2, bom.x, bom.y, 30, 30, this); }else{ g.drawImage(image3, bom.x, bom.y, 30, 30, this); } //让爆炸进行 bom.lifeDown(); if(bom.life==0){ boom.remove(bom); } } } //画出坦克的函数 public void drawTank(int x,int y,Graphics g,int direct,int type){ switch(type){ case 0: g.setColor(Color.cyan); break; case 1: g.setColor(Color.yellow); break; } switch(direct){ case 0://向上走 g.fill3DRect(x, y, 5, 30, false); g.fill3DRect(x+15, y, 5, 30, false); g.fill3DRect(x+5, y+5, 10, 20,false); g.fillOval(x+5, y+10, 10, 10); g.drawLine(x+10, y+15, x+10, y); g.drawOval(x+5, y+10, 10, 10); break; case 3://向右走 g.fill3DRect(x-5, y+5, 30, 5, false); g.fill3DRect(x-5, y+20, 30, 5, false); g.fill3DRect(x, y+10, 20, 10, false); g.fillOval(x+5, y+10, 10, 10); g.drawLine(x+10, y+15, x+25, y+15); g.drawOval(x+5, y+10, 10, 10); break; case 1://向下走 g.fill3DRect(x, y, 5, 30, false); g.fill3DRect(x+15, y, 5, 30, false); g.fill3DRect(x+5, y+5, 10, 20,false); g.fillOval(x+5, y+10, 10, 10); g.drawLine(x+10, y+15, x+10, y+30); g.drawOval(x+5, y+10, 10, 10); break; case 2://向右走 g.fill3DRect(x-5, y+5, 30, 5, false); g.fill3DRect(x-5, y+20, 30, 5, false); g.fill3DRect(x, y+10, 20, 10, false); g.fillOval(x+5, y+10, 10, 10); g.drawLine(x+10, y+15, x-5, y+15); g.drawOval(x+5, y+10, 10, 10); break; } } @Override public void keyTyped(KeyEvent e) { } @Override public void keyPressed(KeyEvent e) { // TODO Auto-generated method stub if(e.getKeyCode()==KeyEvent.VK_UP){ this.mytank.setDirect(0); this.repaint(); this.mytank.moveUp(); } else if(e.getKeyCode()==KeyEvent.VK_DOWN){ this.mytank.setDirect(1); this.repaint(); this.mytank.moveDown(); } else if(e.getKeyCode()==KeyEvent.VK_LEFT){ this.mytank.setDirect(2); this.repaint(); this.mytank.moveLeft(); } else if(e.getKeyCode()==KeyEvent.VK_RIGHT){ this.mytank.setDirect(3); this.repaint(); this.mytank.moveRight(); } } @Override public void keyReleased(KeyEvent e) { // TODO Auto-generated method stub if(e.getKeyCode()==KeyEvent.VK_SPACE){ if(this.mytank.ss.size()<=4){ this.mytank.fire(); } } } @Override public void run() { // TODO Auto-generated method stub //每隔100毫秒重绘 while(true){ System.out.println("sleep"); try { Thread.sleep(30); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } //判断是否击中 for(int i=0;i<mytank.ss.size();i++){ Bullet mb = mytank.ss.get(i); //判断子弹是否有效 if(mb.isAlive){ //取出每一个坦克,与子弹判断是否击中 for(int j=0;j<ets.size();j++){ //取出坦克 EnemyTank et = ets.get(j); if(et.isLive){ this.hittank(mb, et); } } } } this.repaint(); } } } //子弹类 class Bullet implements Runnable{ int x; int y; int direct; int speed=1; boolean isAlive = true; public Bullet(int x,int y,int direct){ this.x=x; this.y=y; this.direct = direct; } @Override public void run() { // TODO Auto-generated method stub while(true){ try { Thread.sleep(25); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } switch(direct){ case 0: y-=speed; break; case 1: y+=speed; break; case 2: x-=speed; break; case 3: x+=speed; break; } //子弹何时死亡? //判断子弹到达边界 if(x<-1||x>501||y<-1||y>501){ this.isAlive=false; break; } } } } //坦克类 class Tank{ //坦克的种类 int type; public int getType() { return type; } public void setType(int type) { this.type = type; } //坦克的速度 int speed = 1; public int getSpeed() { return speed; } public void setSpeed(int speed) { this.speed = speed; } public int getDirect() { return direct; } public void setDirect(int direct) { this.direct = direct; } int direct = 0; //坦克的横纵坐标 int x=0; public int getX() { return x; } public void setX(int x) { this.x = x; } public int getY() { return y; } public void setY(int y) { this.y = y; } int y=0; public Tank(int x,int y){ this.x=x; this.y=y; } } class MyTank extends Tank{ Bullet mb = null; public MyTank(int x,int y){ super(x,y); } Vector<Bullet> ss = new Vector<Bullet>(); //开火能力 public void fire(){ switch(this.direct){ case 0: mb = new Bullet(this.getX()+10,this.getY(),0); ss.add(mb); break; case 1: mb = new Bullet(this.getX()+10,this.getY()+30,1); ss.add(mb); break; case 2: mb = new Bullet(this.getX()-5,this.getY()+15,2); ss.add(mb); break; case 3: mb = new Bullet(this.getX()+25,this.getY()+15,3); ss.add(mb); break; } Thread t = new Thread(mb); t.start(); } public void moveUp(){ y-=speed; } public void moveRight(){ x+=speed; } public void moveDown(){ y+=speed; } public void moveLeft(){ x-=speed; } } class EnemyTank extends Tank{ boolean isLive = true; public EnemyTank(int x,int y){ super(x, y); } } class Boom{ int x; int y; int life = 9;//爆炸的时间过程 boolean isLive = true; public Boom(int x, int y){ this.x=x; this.y=y; } //过程减少 public void lifeDown(){ if(life>0){ life--; }else{ this.isLive=false; } } } ``` ```
JAVA数据结构 用栈替换所有与pattern匹配的子树为bitree
问题:改了很多次,左边的树不匹配,但是右边的树匹配,怎么回到左节点看接下来的树是否匹配啊!问题应该在replaceALL方法里。 ![图片说明](https://img-ask.csdn.net/upload/201912/28/1577507308_187767.jpg) ![图片说明](https://img-ask.csdn.net/upload/201912/28/1577506948_684289.png) ``` //10-24 以中根和后根遍历序列构造二叉树,替换所有与pattern匹配的子树为bitree。 public class BinaryTree<T> { public BinaryNode<T>root; public BinaryTree() { this.root = null; } public boolean isEmpty() //判断是否是空 { return this.root == null; } public String toString()//输出带空子树先跟序列 { return toString(this.root); } public String toString(BinaryNode<T>p) { if(p==null) return "^"; return p.data.toString()+""+toString(p.left)+toString(p.right); } public BinaryTree(T inlist[],T postlist[]) { this.root=BinaryTreecreate(inlist,0,inlist.length-1,postlist,0,postlist.length-1); } //由后根遍历的次序可知,该二叉树的根是potlist[n-1];改节点必定在中根次序中 //由中根遍历次序可知,Inlist[i]节点前段节点在根的左子树上,inlist[i]后的所有节点在根节点的右子树上 private BinaryNode<T> BinaryTreecreate(T[] inlist, int inbegin, int inend, T[] postlist, int postbegin, int postend) { if (postbegin < 0 || inbegin > inend) //递归结束条件 return null; BinaryNode<T> p = new BinaryNode<T>(postlist[postend]); int j = inbegin; //标记查找到的根结点的位置 while (j <= inend&&inlist[j] != postlist[postend]) { //遍历查找 j++; } p.left = BinaryTreecreate(inlist, inbegin, j - 1, postlist, postbegin, postbegin + j - inbegin - 1); //递归构造左子树 p.right = BinaryTreecreate(inlist, j + 1, inend, postlist, postbegin + j - inbegin, postend - 1); ////递归构造右子树 return p; } public BinaryTree(T[] prelist)//构造二叉树,prelist数组指定二叉树标明空子树的先根遍历序列 { this.root=create(prelist); } //以从i开始的标明空子树的先根序列,创建一颗以prelist[i]为根的子树,返回根结点,递归方法 private int i=0; private BinaryNode<T>create(T[] prelist) { BinaryNode<T>p=null; if(i<prelist.length) { T elem=prelist[i]; i++; if(elem!=null) //不能elem!="kong",因为T不一定是String { p=new BinaryNode<T>(elem); //创建叶子结点 p.left=create(prelist); //创建P的左子树,递归调用 p.right=create(prelist); //创建P的右子树,递归调用 } } return p; } //比较 public boolean equals(BinaryNode<T> p,BinaryNode<T> q) { return (p==null&&q==null)||(p!=null&&q!=null)&&(q.data.equals(p.data))&& equals(p.left,q.left)&&equals(p.right,q.right); } //对象复制 BinaryTree(BinaryTree<T> bitree) //实现BinaryTree<T>二叉树类声明的深拷贝构造方法 { this.root = copy(bitree.root); } private BinaryNode<T> copy(BinaryNode<T> p) //方法实现 { BinaryNode<T> q = null; if (p != null) { q = new BinaryNode<T>(p.data); q.left = copy(p.left); q.right = copy(p.right); } return q; } public void replaceAll(BinaryTree<T> pattern, BinaryTree<T> bitree) { if(equals(pattern)) this.root=this.copy(bitree.root); else ** this.replaceall(this.root,pattern.root,bitree.root); ** //可不写 } **_ public void replaceall(BinaryNode<T> p,BinaryNode<T> pattern,BinaryNode<T> bitree) //parent指向this的结点;pattern指向pattern的结点;bitree指向bitree的结点; { //parent指向this的结点;p指向pattern的结点;m指向bitree的结点; System.out.print("替换后:"); //优先遍历的非递归算法 P154 LinkedStack<BinaryNode<T>>stack=new LinkedStack<BinaryNode<T>>();//创建的这个空栈为链式栈,使用单链表存储数据且实现栈接口 P91 while(p!=null||!stack.isEmpty())//P非空或栈非空时 { if( p!= null&&pattern!=null) { if(this.equals(p.left, pattern)) { // System.out.print(pattern); p.left=this.copy(bitree); // stack.push(p); // p=p.left; } if(this.equals(p.right, pattern)) { // System.out.print(pattern); p.right=this.copy(bitree); p=stack.pop(); // p=p.right; } else { // // System.out.print(p.data); stack.push(p); p=p.left; } } //p==null&&! if(stack.isEmpty()||p==null) { // // System.out.print("^"); // p=stack.pop(); // P指向出栈结点 if(stack.isEmpty()) ** p=p.right; // 进入右子树** else if (p==null) { p = stack.pop(); p = p.right; } } // System.out.print(""); //} } }**_ public static void main(String args[]) { String[] parent={"A","B","D",null,"G",null,null,"D",null,"G",null,null,"C","E",null,null,"F","H",null,null,"D",null,"G"}; String[] inlist={"D","G","B","A","E","C","H","F"}; //中根次序 String[] postlist={"G","D","B","E","H","F","C","A"}; //后根次序 String[] pattern1={"D",null,"G"}; String[] bitree1={"M","D",null,"G"}; BinaryTree<String> values=new BinaryTree<String>(parent); BinaryTree<String> pattern=new BinaryTree<String>(pattern1); BinaryTree<String> bitree=new BinaryTree<String>(bitree1); BinaryTree<String> tree=new BinaryTree<String>(inlist,postlist); System.out.println("构造出来的二叉树以先根次序输出为:"+tree); System.out.println("替换前树values的序列: "+values); //输出替换前树values的序列 System.out.println("pattern序列: "+pattern); System.out.println("bitree序列: "+bitree); ** values.replaceAll(pattern,bitree); //替换** // System.out.print(values); //System.out.println("替换后树values的序列: "+values); //输出替换后树values的序列 } } ```
如何在java里调用使用get方法,参数以application/x-www-form-urlencoded方式传递的web接口?
想要在java代码里调用一个web接口,该接口通过postman测试是可以成功的,如图: ![图片说明](https://img-ask.csdn.net/upload/201901/16/1547608544_517344.png) 但是以如下方式写在java代码里却无法成功,请问有人知道是为什么吗? ``` String path="http://192.168.1.93:9000/offer?calip=192.168.1.20&bmcip=192.168.1.11"; String data="calip=192.168.1.20&bmcip=192.168.1.11"; try { URL url = new URL(path); //打开和url之间的连接 HttpURLConnection conn = (HttpURLConnection) url.openConnection(); //请求方式,默认为get //设置通用的请求属性 conn.setRequestProperty("accept", "*/*"); conn.setRequestProperty("connection", "Keep-Alive"); conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)"); conn.setRequestProperty("Content-Type","application/x-www-form-urlencoded"); conn.setConnectTimeout(5000); conn.setReadTimeout(5000); conn.setDoOutput(true); conn.setDoInput(true); conn.connect(); //获取URLConnection对象对应的输出流 PrintWriter out = new PrintWriter(conn.getOutputStream()); //发送请求参数即数据 out.print(data); //缓冲数据 out.flush(); out.close(); //获取URLConnection对象对应的输入流 InputStream is = conn.getInputStream(); //构造一个字符流缓存 BufferedReader br = new BufferedReader(new InputStreamReader(is)); String str = ""; while ((str = br.readLine()) != null) { System.out.println("from ipmi"+str); } //关闭流 is.close(); conn.disconnect(); System.out.println("发送结束"); } catch (Exception e) { e.printStackTrace(); } ```
[JAVA真的非常非常新的新手]关于继承的构造方法的问题
``` 1. class Father{ 2. private String name ="father" ; 3. int age =38; 4. public Father(){ 5. System. out.println("Non-parametric construction method of father." ); 6. System. out.println(name +" " +age ); 7. System. out.println("--------------------------------------------------" ); 8. } 9. public Father(String name ,int age){ 10. this.name =name ; 11. this.age =age ; 12. System. out.println("Parametric construction method of father." ); 13. System. out.println(name +" " +age ); 14. System. out.println("--------------------------------------------------" ); 15. } 16. public String getName(){ 17. return name ; 18. } 19. public int getAge(){ 20. return age ; 21. } 22. 23. } 24. 25. class Son extends Father{ 26. private String name ="son" ; 27. int age =18; 28. public Son(){ 29. System. out.println("Non-parametric construction method of son." ); 30. System. out.println(name +" " +age ); 31. System. out.println("--------------------------------------------------" ); 32. } 33. public Son(String name, int age ){ 34. super( name, age); 35. this. name= name; 36. this.age =age ; 37. System. out.println("Parametric construction method of son." ); 38. System. out.println(name +" " +age ); 39. System. out.println("--------------------------------------------------" ); 40. } 41. public String getName(){ 42. return name ; 43. } 44. public int getAge(){ 45. return age ; 46. } 47. } 48. 49. 50. public class hello { 51. public static void main(String[]args){ 52. Son p1= new Son); //新建一个Son对象,调用Son的无参构造方法,在此之前先访问父类的无参构造方法(对应运行结果1,2,3,4,5,6行) 53. Son p2= new Son("Paul" ,17);//新建一个Son对象,调用Son的含参构造方法,在此之前先访问父类的含参构造方法(7,8,9,10,11,12行) Question:为什么父类中打印出来的年龄和姓名变成了子类的年龄 54. p1.getName(); 和姓名? 并且即使把代码中9,10行注释掉运行结果也还是这样?不应该只是完成父类参数的初始化吗?还是程序的编写哪里出错了? 55. p1.getAge(); //调用P1,P2的getName和getAge方法并打印出来(13行) 56. p2.getName(); 57. p2.getAge(); 58. System. out.println(p1 .getName()+" "+ p1.getAge()+ " "+p2 .getName()+" "+p2.getAge()); 59. Father e=new Father();//新建一个father对象并调用它的getName和getAge方法并打印出来//这里为了区别构造方法和打印出来的age值,给打印的age+1 60. e.getName(); //这里之所以打印出来的还是38+1是因为新建了一个father对象所以新开辟了一片堆空间储存Name和Age值 61. e.getAge(); 62. System. out.println(e .getName()+" "+ ( e.getAge()+1)); 63. } 64. } ``` 运行结果: 1. Non-parametric construction method of father. 2. father 38 3. -------------------------------------------------- 4. Non-parametric construction method of son. 5. son 18 6. -------------------------------------------------- 7. Parametric construction method of father. 8. Paul 17 9. -------------------------------------------------- 10. Parametric construction method of son. 11. Paul 17 12. -------------------------------------------------- 13. son 18 Paul 17 14. Non-parametric construction method of father. 15. father 38 16. -------------------------------------------------- 17. father 39 问题: 1,为什么父类中打印出来的年龄和姓名变成了子类的年龄 和姓名? 并且即使把代码中9,10行注释掉运行结果也还是这样?不应该只是完成父类参数的初始化吗?还是程序的编写哪里出错了? 2,子类中用super(...)访问父类的带参构造方法有什么意义?跟访问无参方法有何区别? 照我的运行结果来说难道子类使用super(...)访问了父类的带参构造方法,子类就会将传递给它的参数再传递给父类让父类完成初始化吗? 目前的只是储备:看了一点书的视频,刚看完接口,关于JAVA的内存问题视频教程中略有涉及,看的书中尚未涉及,看过几篇讲JAVA内存问题的帖子,不过大概知道JAVA内存的三个区的划分,但是还是不很了解,很多时候比较模糊,特别是关于构造方法到底做些什么非常不了解 非常谢谢各位Orz
JAVA 实现接口方法时报错 implement a supertype method
public interface MultimediaControl { public void play(); public void stop(); public void previous(); public void next(); } public class AudioPlayer extends Product implements MultimediaControl { String audioSpecification; ItemType mediaType; @Override //The method play() of type AudioPlayer must override or implement a supertype method public void play() { System.out.println("Playing"); } @Override //The method stop() of type AudioPlayer must override or implement a supertype method public void stop() { System.out.println("Stopped"); } @Override //The method previous() of type AudioPlayer must override or implement a supertype method public void previous() { System.out.println("To the previous"); } @Override public void next() //The method next() of type AudioPlayer must override or implement a supertype method{ System.out.println("To the Next"); } public AudioPlayer(String name, ItemType Type) { super(name); //The constructor Product(String) is undefined mediaType = Type; } } 还有构造函数中调用父类带参构造函数, 父类中的构造函数 : public Product(String Name) { name = Name; serialNumber = currentProductionNumber; manufacturedOn = new Date(); } 明明有带String参数的构造?为什么会提示这些错误呢
关于Java中this深层次的问题
目前我所知道的this的用法包括以下几种: (1)this代表对象:调用该函数的对象。 (2)构造函数访问本类中的构造函数,但必须放在首行。this(), this(name); (3)当成员变量和局部变量重名,可以用this来代表成员变量(如果在本类中用到本类的对象。就用this) (4)this指代本类实现的的接口。 问题: (1)除了这四个,还有其他的用法吗? (2)请问this实现原理是什么?比如第四个,怎么指代接口的(应该指代实现接口的方法吧?)。还有其他三个的实现原理呢呢?
GWT开发RPC调用过程中的对象序列化问题
<p>在GWT的RPC调用过程中,需要传递参数,而这些参数必须是序列化过的,如果是基本类型、或者基本类型的数组,都是默认序列化的,如果用户自定义的类,就必须实现java.io.Serializable接口。</p> <p> </p> <p>在这里需要注意的一个小点就是,序列化后的类,必须提供一个默认构造函数,即不带参数的构造函数,这点要求好像是GWT强制要求的,因为我并没有在Java规范中看到实现序列化,必须提供默认构造函数这一条。</p> <p> </p> <p>如果是我疏忽了的话,望知道的朋友提醒,谢谢</p>
Java中多线程同步锁报无效指针异常是何原因,求大神解答!
/* 需求: 使用lock接口实现商品的生产和销售的动态平衡 思路: 1、创建被共同操作的数据类Resource,并通过多态引用分别创建lock和condition子类对象以及资源的获取和赋值方法 2、创建两个相反操作即生产和销售的类同时实现Runnable接口,并覆盖run方法 3、在主函数中,创建资源对象,并作为共同参数分别传递给生产和销售两个线程实现类的构造函数 4、分别将生产和销售类的对象作为参数,传给两个线程,并各自开启线程 */ package com.horse146; import java.util.concurrent.locks.*; class ProducerConsumerDemo { public static void main(String[] args) //主函数 { Resource r=new Resource(); Producer p=new Producer(r); Consumer c=new Consumer(r); Thread t1=new Thread(p); Thread t2=new Thread(c); t1.start(); t2.start(); } } class Resource //被共同操作的数据类 { String name; int id; boolean flag; Lock lock=new ReentrantLock();//创建锁对象 Condition pro=lock.newCondition(); //用上面创建的锁对象,调用其newCondition方法,创建Condition子类对象,实现对lock锁的等待唤醒操作 Condition con=lock.newCondition(); public void set(String name)throws InterruptedException{//创建赋值方法,并针对等待异常抛出 lock.lock(); try{ while(flag) pro.await();//lock锁下面的Pro线程等待 this.name=name+"----"+id; System.out.println(Thread.currentThread().getName()+"生产出"+this.name); flag=true; con.signal();//lock锁下面的con线程唤醒 } finally{ lock.unlock();//解锁 } } public void get()throws InterruptedException{//创建取值方法,对针对等待异常抛出 lock.lock(); try{ while(!flag) con.await(); System.out.println(Thread.currentThread().getName()+"消费了"+this.name); flag=false; pro.signal();//Pro线程唤醒 } finally{ lock.unlock(); } } } class Producer implements Runnable//生产者类实现Runnable接口 { private Resource r; Producer(Resource r){ this.r=r; } public void run(){ while(true){ try{r.set("商品");} catch(InterruptedException e){} } } } class Consumer implements Runnable//消费者类实现Runnable接口 { private Resource r; Consumer(Resource r){ this.r=r; } public void run(){ while(true){ try{r.get();} catch(InterruptedException e){} } } }
求大神回答 java的swing题目
1.创建项目Lab37,添加类MainFrame,继承自JFrame,实现ActionListener接口。 2.添加以下成员属性 a)JTree类型的treeDir b)String类型的dirName c)JSplitPane类型的sp d)JTable类型的fileInfo 3.构造方法 a)设置标题为“文件信息查看器” b)创建工具栏,并添加一个“打开”按钮。注册按钮事件监听对象为this c)构造一个只有一个节点,显示“未选择目录”的树,引用到treeDir d)将treeDir加入到sp的左侧 e)将fileInfo设置为一个表头显示"文件名","文件大小"。只有一行数据"未选择文件","0"的表。 f)将fileInfo加入到sp的右侧 g)将工具栏放置在窗体的North方位,sp放置在Center。设置窗体大小为600*480,可见。 4.添加一个方法makeTree,没有返回值,参数String rName, String[] nName。方法逻辑如下: a)以rName为内容定义一个节点作为根节点root。 b)定义一个DefaultMutableTreeNode数组nodes,数组的个数为nName数组元素的数目。 c)利用循环,将nName数组的每一个内容构建一个节点,并复制到nodes数组的元素。将当前这个nodes的节点添加到root的子节点。 d)创建根为root的树引用到treeDir。 e)将treeDir放入JScrollPane容器再添加到sp的左侧。sp.setLeftComponent(new JScrollPane(treeDir)); 5.添加一个方法makeTable,没有返回值,参数File[] nFile a)如果nFile的内容为空,则返回。 b)定义DefaultTableModel对象dtm,获取fileInfo对象的模型。 c)清除原有数据行。 d)定义字符串数组title,内容为"文件名","文件大小"。将title设置为表头作为表头。dtm.setColumnIdentifiers(title); e)定义一个2元素的String数组data,循环遍历nFile,将每个元素的文件名赋值到data[0],文件大小赋值到data[1]。将data添加为表格的一行。dtm.addRow(data); 6.添加一个方法openFile,没有返回值,不需要参数。方法处理逻辑如下 a)定义一个JFileChooser对象fileChooser。 b)调用fileChooser的setFileSelectionMode方法,参数JFileChooser.DIRECTORIES_ONLY。使得只能选择目录。 c)打开文件对话框,定义临时int变量rVal记录返回值。 d)如果是按“确定”返回,则将用户选择的目录路径赋值到dirName。根据dirName构建文件对象,调用makeTree方法和makeTable方法。 7.实现actionPerformed方法 a)判断事件源是否为按钮。 b)如果是按钮事件,则调用openFile方法 8.主方法 a)构造MainFrame对象。 具体图片如下![![![![图片说明](https://img-ask.csdn.net/upload/201506/07/1433674821_106203.png)图片说明](https://img-ask.csdn.net/upload/201506/07/1433674815_5161.png)图片说明](https://img-ask.csdn.net/upload/201506/07/1433674859_111744.png)图片说明](https://img-ask.csdn.net/upload/201506/07/1433674797_418237.png)
JAVA 现有3老师个分别管理3个班级班级学生人数不限(即1个老师管理1个班级),录入学生期末成绩。
实现功能如下: 1. 显示所有老师信息及老师下面学生成绩; public void showAllMeassage(); 2. 在小熊老师下新增zz学生,添加该学生各科成绩,可以不用控制台录入,直接通过构造方法初始信息后添加 ;public boolean addStudent(String teacherName,Student s); 3. 删除小熊老师下的dd学生信息;public boolean deleteStudent(String teacherName,String studentName); 4. 删除兔子老师,将兔子老师下面的学生信息放到小鹿老师下面; public boolean deleteTeacher(String teacherName); 5. 修改小鹿老师下面mm学生的英语成绩改为100; public boolean updateStudent(String teacherName,String studentName); 具体要求 老师类里面属性有 编号 姓名,密码 学生表里面有 编号 姓名 语文成绩 数学成绩 英语成绩 要求用到抽象类,接口 用Map<老师姓名,List<学生>> 实现数据存取 以上方法定义按照后面要求定义,参数返回类型与要求一致;在main方法里面定义菜单循环调用输出结果,调用时传参数值按上面要求直接传,不用控制台输入。
文件无法写入!还有NullPointerException的问题
(1) 设计一个复数运算接口OperatorListener,定义抽象方法Complex add(Complex z) (2) 设计一个复数类Complex,此复数类实现OperatorListener接口,该类定义 私有属性:实部,虚部 方法:返回此复数的详细信息String toString(),输出格式例如3+4i 实现接口里的Complex add(Complex stu)抽象方法,实现复数的相加 构造方法:有参构造方法初始化成员变量 (3) 设计测试类Test,主函数要求产生两个复数对象,对象的成员变量值来自命令行参数,调用add方法,实现两个复数的相加,把相加的结果值写入到c:/ComputeInfo.txt文件中,并处理所有的异常信息。 自己写的源代码: (1) public interface OperatorListener{ public Complex add(Complex z); } (2) public class Complex implements OperatorListener{ private double real; private double imag; public Complex(){ } public Complex(double real,double imag){ this.real=real; this.imag=imag; } public Complex(Complex c){ real=c.real; imag=c.imag; } public double getReal(){ return real; } public double getImag(){ return imag; } public String toString(){ System.out.println(real+"+"+imag+"i"); return null; } public Complex add(Complex stu){ Complex p=new Complex(); p.real=real+stu.getReal(); p.imag=imag+stu.getImag(); return p; } } (3) import java.io.*; public class Test { public static void main(String[] args){ // TODO 自动生成的方法存根 try{ double x1,y1; double x2,y2; x1=Double.parseDouble(args[0]); y1=Double.parseDouble(args[1]); x2=Double.parseDouble(args[2]); y2=Double.parseDouble(args[3]); Complex com1=new Complex(x1,y1); Complex com2=new Complex(x2,y2); Complex com=com1.add(com2); File f=new File("C:\\ComputeInfo.txt"); FileOutputStream file=new FileOutputStream(f,true); file.write(com.toString().getBytes("utf-8")); file.close(); } catch(ArrayIndexOutOfBoundsException e){ System.out.println("你还没有输入呢,请输入数值!"); } catch(NumberFormatException e){ System.out.println("你输入的是字符,请输入数值!"); } catch(IOException e){ System.out.println("写入文件不成功!"); } } } 在eclipse上可以显示结果,但是下面多出了两行: Exception in thread "main" java.lang.NullPointerException at Test.main(Test.java:16) 问题出在了file.write(com.toString().getBytes("utf-8")); 这一行 也无法写入到指定文件,想求教下这一行怎么改?
JAVA多线程和以下程序的区别
学习多线程了解到 实现线程有两种方式: 1.继承Thread类,重写run方法,在调用start方法。 2.实现Runnable接口,重写run方法。在传给Thread构造器,调用时调用Thread的start方法。 以下这个我也觉得也是在多个一起运行啊,为什么不叫多线程呢,而且并没有实现以上两种方式 public class Thread_setPriority { public static void main(String[] args) { Thread nor = new Thread() { public void run() { for(int i=0;i<10000;i++) { System.out.println("nor"); } } }; Thread max = new Thread() { public void run() { for(int i=0;i<10000;i++) { System.out.println("max"); } } }; Thread min = new Thread() { public void run() { for(int i=0;i<10000;i++) { System.out.println("min"); } } }; max.setPriority(Thread.MAX_PRIORITY); min.setPriority(Thread.MIN_PRIORITY); min.start(); nor.start(); max.start(); } }
泛型集合的遍历,返回什么类型
import java.lang.reflect.Field; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; import com.sun.org.apache.commons.beanutils.BeanUtils; public class DBOperateTUtilts { 方法1 public static <E> List<E> query(String sql, Class<E> clazz) { Connection conn = null; PreparedStatement pstmt = null; ResultSet rs = null; Object tempStr = null; List<T> list = new ArrayList<T>(); try { conn = DBConnectUtils.getConnection(); pstmt = conn.prepareStatement(sql); rs = pstmt.executeQuery(); while (rs.next()) { // newInstance实际上是把new这个方式分解为两步,即,首先调用class的加载方法加载某个类,然后实例化。 // 我们可以在调用class的静态加载方法forName时获得更好的灵活性,提供给了我们降耦的手段。 // newInstance: 弱类型。低效率。只能调用无参构造。 // new: 强类型。相对高效。能调用任何public构造。 E obj = clazz.newInstance(); if (obj instanceof String) { // ResultSet的下标从1开始 obj = (E) rs.getString(1); } else { // Field 提供有关类或接口的单个字段的信息,以及对它的动态访问权限 // getDeclaredFields()返回Class中所有的字段,包括私有字段 // getFields 只返回公共字段,即有public修饰的字段 // field,域是一种属性,可以是一个类变量,一个对象变量,一个对象方法变量或者是一个函数的参数。 Field[] fields = obj.getClass().getDeclaredFields(); // 遍历域 for (Field field : fields) { try { // 反射获取对象成员的字段值 tempStr = rs.getObject(field.getName()); } catch (SQLException e) { tempStr = ""; } // 置是否允许访问,而不是修改原来的访问权限修饰词 field.setAccessible(true); // 把对象的属性数据封装到对象中 BeanUtils.setProperty(obj, field.getName(), tempStr); } } list.add(obj); } } catch (Exception e) { e.printStackTrace(); throw new RuntimeException(e); } finally { DBCloseUtils.closeCSR(conn, pstmt, rs); } return list; } 方法2 public static <T> List<T> query(String sql, Class<T> clazz, Object[] parameters) { Connection conn = null; PreparedStatement pstmt = null; ResultSet rs = null; ResultSetMetaData metaData = null; List<T> list = new ArrayList<T>(); int index = 1; try { pstmt = conn.prepareStatement(sql); } catch (SQLException e) { e.printStackTrace(); } if (parameters != null && parameters.length != 0) { for (int i = 0; i < parameters.length; i++) { try { // pstmt.setObject(第几个参数, 替换成什么); pstmt.setObject(index, parameters[i]); } catch (SQLException e) { e.printStackTrace(); } } } try { rs = pstmt.executeQuery(sql); } catch (SQLException e) { e.printStackTrace(); } // 封装resultset try { metaData = rs.getMetaData(); } catch (SQLException e) { e.printStackTrace(); }// 取出列的信息 int columnLength = 0; try { columnLength = metaData.getColumnCount(); } catch (SQLException e) { e.printStackTrace(); }// 获取列数 try { while (rs.next()) { // 通过反射机制创建一个对象 T result = clazz.newInstance(); for (int i = 0; i < columnLength; i++) { String metaDataKey = metaData.getColumnName(i + 1); Object resultsetValue = rs.getObject(metaDataKey); if (resultsetValue == null) { resultsetValue = ""; } Field field = clazz.getDeclaredField(metaDataKey); field.setAccessible(true); field.set(result, resultsetValue); } list.add(result); } } catch (Exception e) { e.printStackTrace(); throw new RuntimeException(e); } return list; } }
Spring Boot配置Session监听无效。
我有一个spring boot (v1.5.9.RELEASE)项目,想要对session进行管理/监听,实现了HttpSessionListener和HttpSessionAttributeListener这两个接口,在MySessionListener中使用@WebListener注解,在启动类中使用@SpringBootApplication注解 但是经过测试,访问网页(ftl页面)无法触发sessionCreated()方法,session过期时也无法触发sessionDestroyed()方法;用户登陆时调用request.getSession().setAttribute()或者session().setAttribute()都无法触发attributeAdded()方法。 程序启动时可以输出构造方法中的内容 2018-01-22 18:02:49.761 INFO 35600 --- [ost-startStop-1] c.t.x.c.listener.MySessionListener : MySessionListenerInitialized 请问有人知道这是为什么吗 代码如下: DemoApplication.java ``` @SpringBootApplication @ServletComponentScan public class DemoApplication { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } } ``` MySessionListener.java ``` @WebListener public class MySessionListener implements HttpSessionListener, HttpSessionAttributeListener { private final static Log log = LogFactory.getLog(MySessionListener.class); // 程序启动时可以在控制台中输出这句话 public MySessionListener() { log.info("MySessionListenerInitialized"); } @Override public void sessionCreated(HttpSessionEvent se) { log.info("sessionCreated-----" + se.getSession().getId()); } @Override public void sessionDestroyed(HttpSessionEvent se) { log.info("sessionDestroyed-----" + se.getSession().getId()); } @Override public void attributeAdded(HttpSessionBindingEvent se) { log.info("attributeAdded: "+se.getSession().getId()); } @Override public void attributeRemoved(HttpSessionBindingEvent se) { log.info("attributeRemoved: "+se.getSession().getId()); } @Override public void attributeReplaced(HttpSessionBindingEvent se) { log.info("attributeReplaced: "+se.getSession().getId()); } } ``` 还有就是使用springbean的配置方式同样无效 ``` @Configuration public class MyWebConfiguration extends WebMvcConfigurerAdapter { @Bean public ServletListenerRegistrationBean<EventListener> sessionListener() { ServletListenerRegistrationBean<EventListener> sessionListener = new ServletListenerRegistrationBean<>(); sessionListener.setListener(new MySessionListener()); return sessionListener; } } ```
Spring事务的问题,bulkUpdate,或query.executeUpdate
今天在测试spring任务调度时,突然发现我配的声明事务不起作用了,找了好久才发现不是我的事务的问题,是我在Dao中用了一个方法有问题 方法如下: public void updateByIds(final Set<String> updateIds)throws DaoException{ try { String queryString="update from Yaoyueyingyue y set y.state='2' where y.yaoyueid in (?)"; getHibernateTemplate().bulkUpdate(queryString, updateIds.toArray()); } catch (Exception e) { e.printStackTrace(); throw new DaoException(this.getClassName()+e.getMessage()); } updateIds是一个包含要更新的编号集合,我发现用这个方法在我Manager中调用Dao事务就不起作用了,后来又改成这样 public void updateByIds(final Set<String> updateIds)throws DaoException{ try { getHibernateTemplate().execute(new HibernateCallback(){ final String hql="update Yaoyueyingyue y set y.state=2 where yaoyueid in (:yaoyueid)"; public Object doInHibernate(Session session) throws HibernateException, SQLException { Query query=session.createQuery(hql); query.setParameterList("yaoyueid", updateIds); query.executeUpdate(); return null; } }); } catch (Exception e) { e.printStackTrace(); throw new DaoException(this.getClassName()+e.getMessage()); } } 事务还是不行,这两个方法好像不受spring AOP事务管理,只要执行到这个Dao的方法就自动提交了,出来异常也不能回滚,真是郁闷,小弟对这块不是很明白,为什么事务就不行了呢,希望那位牛人,帮我解释下,谢谢了, 我的spring声明事务大概如下: <bean id="atomikosTransactionManager" class="com.atomikos.icatch.jta.UserTransactionManager" init-method="init" destroy-method="close"> <property name="forceShutdown"> <value>true</value></property> </bean> <bean id="atomikosUserTransaction" class="com.atomikos.icatch.jta.UserTransactionImp"> <property name="transactionTimeout" value="300"/> </bean> <bean id="springTransactionManager" class="org.springframework.transaction.jta.JtaTransactionManager"> <property name="transactionManager"><ref bean="atomikosTransactionManager" /></property> <property name="userTransaction"><ref bean="atomikosUserTransaction" /></property> </bean> <aop:config> <!-- This definition creates auto-proxy infrastructure based on the given pointcut, expressed in AspectJ pointcut language. Here: applying the advice named "txAdvice" to all methods on classes named PetStoreImpl. --> <aop:advisor pointcut="execution(* com.goal.log.manager.*.*(..))" advice-ref="txAdvice" /> <aop:advisor pointcut="execution(* com.goal.system.manager.*.*(..))" advice-ref="txAdvice" /> </aop:config> <!-- @Transactional 时要使用下面一行 --> <!-- <tx:annotation-driven transaction-manager="springTransactionManager" proxy-target-class="true"/> --> <!-- Transaction advice definition, based on method name patterns. Defaults to PROPAGATION_REQUIRED for all methods whose name starts with "insert" or "update", and to PROPAGATION_REQUIRED with read-only hint for all other methods.--> <!-- 引用springTransactionManager --> <tx:advice id="txAdvice" transaction-manager="springTransactionManager"> <tx:attributes> <tx:method name="save*" rollback-for="java.lang.Exception"/> <tx:method name="insert*" rollback-for="java.lang.Exception"/> .... <tx:method name="*" read-only="true" rollback-for="java.lang.Exception"/> </tx:attributes> </tx:advice> atomikosTransactionManager这个东西不用管,是一个开源的支持JTA分布式的JAR,希望有人能够为我解答........ [b]问题补充:[/b] 谢谢你的解答,但是我还是不明白你的意思,你是指我的Dao中用了内部类吗,你所指的 “调用updateByIds方法 的代码 跳出你的当前类 然后在别的类调用当前了类的接口中的方法updateByIds ”是指什么意思,能不能说明白点,谢谢了!!! [b]问题补充:[/b] 谢谢你的答复,你的意思我也理解,但好像不是这个问题,因为我并没有像你说的那样在类的内部调用,我的所有方法都是在业务逻辑层调用的Manager层,Manager层我是在Spring中配置了的声明事务的,我给你据个例子: 这两个方法都是Dao中的 方法一: [code="java"] public void updateByIds(final Set<String> updateIds)throws DaoException{ try { /*String queryString="update from Yaoyuepub y set y.state='2' where y.yaoyueid in (?)"; getHibernateTemplate().bulkUpdate(queryString, updateIds.toArray());*/ getHibernateTemplate().execute(new HibernateCallback(){ final String hql="update Yaoyuepub y set y.state=2 where yaoyueid in (:yaoyueid)"; public Object doInHibernate(Session session) throws HibernateException, SQLException { Query query=session.createQuery(hql); query.setParameterList("yaoyueid", updateIds); query.executeUpdate(); return null; } } ); } catch (Exception e) { e.printStackTrace(); throw new DaoException(this.getClassName()+e.getMessage()); } } [/code] 这个方法是把所有的要改的ID都一次性更新调,我是不想执行多条sql,在Manager中调用这个方法事务就起不了作用,还有一个方法,就是普通的更新对象 [code="java"] public void update(T t) throws DaoException { try { getHibernateTemplate().update(t); } catch (Exception e) { throw new DaoException(getClassName() + " update exception...",e); } } [/code] 要是把刚才Manager中调用改成循环执行下面的方法一个一个对象,就是有事务的,所以调用都一样,更类的内部调用应给没有关系的,我认为不管是query.executeUpdate还是spring自己提供的bulkUpdate这两个方法都是要写sql的,目的是满足批量更新和更大的灵活性,但是事务就不行了,我认为肯定可以让声明式事务支持这两个方法,就是不知道怎么配置一下,你可以自己在代码中分别做个例子试试,看看是不是用批量更新事务就控制不了了, 这就是我的理解,还请多多指教,谢谢诶!!! [b]问题补充:[/b] 我测试过了,以为可以了,但是还是不行,下面是我调用的一小部分代码 [code="java"] public void runThread() { Set<String> updateIds = new HashSet<String>(); for (Yaoyueyingyue yaoyueyingyue : yaoyueyingyues) { updateIds.add(yaoyueyingyue.getYaoyueid()); } if (updateIds.size() > 0) { yaoyuepubDao.updateByIds(updateIds); if(true) throw new RuntimeException("AAAAAAAAAAAAAAAAAAAAAAAAA"); yaoyueyingyueDao.updateByIds(updateIds); } [/code] 上面是我Manager中Spring任务调度自动执行的方法的一小部分,我中间估计抛出了异常,但是yaoyuepubDao数据库中都更新了,事务不起作用,我估计其实就是和bulkUpdate方法一样,只要这个方法能用事务控制了的话,应该没问题了 [b]问题补充:[/b] 下面是我在网上拷贝的--------------------------------   Spring的HibernateTemplate提供了Hibernate的完美封装,即通过匿名类实现回调,来保证Session的自动资源管理和事务的管理。其中核心方法是:   java代码: HibernateTemplate.execute(new HibernateCallback() {  public Object doInHibernate(Session session) throws HibernateException {   ....  } }   回调方法提供了session作为参数,有了session,就可以自由的使用Hibernate API编程了。使用了spring的之后,代码修改如下:   web层代码:   java代码: DetachedCriteria detachedCriteria = DetachedCriteria.forClass(Department.class); detachedCriteria.createAlias("employees", "e").add(Restrictions.eq("name", "department")).add(Restrictions.gt(("e.age"), new Integer(20))); departmentManager.findByCriteria(detachedCriteria);   构造detachedCriteria,作为参数传递给departmentManager   业务层代码使用spring,DepartmentManager的findByCriteria如下:   java代码: public List findByCriteria(final DetachedCriteria detachedCriteria) {  return (List) getHibernateTemplate().execute(new HibernateCallback() {   public Object doInHibernate(Session session) throws HibernateException {    Criteria criteria = detachedCriteria.getExecutableCriteria(session);    return criteria.list();   }  }); }   实际上也就是:   java代码: Criteria criteria = detachedCriteria.getExecutableCriteria(session); return criteria.list();   而已   但是该程序代码执行,会抛出强制类型转换异常!   我跟踪了一下spring和Hibernate源代码,原因如下:   spring的HibernateTemplate的execute方法提供的回调接口具有Session作为参数,但是实际上,默认情况下,HibernateTemplate传递给回调接口的session并不是org.hibernate.impl.SessionImpl类,而是SessionImpl类的一个Proxy类。之所以替换成为一个Proxy类,HibernateTemplate的注释说明,Proxy提供了一些额外的功能,包括自动设置Cachable,Transaction的超时时间,Session资源的更积极的关闭等等。   java代码: private boolean exposeNativeSession = false; ...   execute方法内部: Session sessionToExpose = (exposeNativeSession ? session : createSessionProxy(session));   但是遗憾的是,Hibernate的DetachedCriteria的setExecutableCriteria方法却要求将session参数强制转为SessionImpl,但是spring传过来的却是一个Proxy类,因此就报错了。   java代码: public Criteria getExecutableCriteria(Session session) {  impl.setSession( (SessionImpl) session ); // 要求SessionImpl,Spring传递的是Proxy  return impl; }   解决方法,禁止Spring的HibernateTemplate传递Proxy类,强制要求它传递真实的SessionImpl类,即给exexute方法增加一个参数,提供参数为true,如下:   java代码: public List findByCriteria(final DetachedCriteria detachedCriteria) {  return (List) getHibernateTemplate().execute(new HibernateCallback() {   public Object doInHibernate(Session session) throws HibernateException {    Criteria criteria = detachedCriteria.getExecutableCriteria(session);    return criteria.list();   }  }, true); } [b]问题补充:[/b] bulkUpdate这个方法按你给的源码,那我是用错了,但是你所说的我的模拟异常不再AOP的事务之内,我就不同意你的观点了,[code="java"] if (updateIds.size() > 0) { yaoyuepubDao.updateByIds(updateIds); // 事务开启 执行updateByIds 事务提交 if(true) throw new RuntimeException("AAAAAAAAAAAAAAAAAAAAAAAAA"); yaoyueyingyueDao.updateByIds(updateIds); // 事务开启 执行updateByIds 事务提交 } [/code] 我这段代码是两个Dao的操作,而这两个Dao的操作是被封装在一个Manger中的方法中的,Manager的每个方法都是有事务的,在操作玩第一个Dao后抛出一个RunTime异常,这时候第一个Dao操作已经执行了,这时候事务应该回滚的,不应该去更新的第一个Dao的操作,Manager中本来就业务层,中间有好多的Dao操作,事务应该控制这些Dao要不都提交,要不都回滚,你说呢,而你说的在11-12行之间加异常,那在一个Dao中,再说的的Dao是没有配事务的,又何谈回滚呢,要是把我上面两个Dao操作改成普通的对象更新,是可以回滚的,这个我肯定 比如这样 [code="java"] yaoyuepubDao.update(yaoyuepub); if(true) throw new RuntimeException("AAAAAAAAAAAAAAAAAAAAAAAAA"); yaoyueyingyueDao.update(yaoyueyingyue); [/code] 这个时候如果抛出异常,yaoyuepub是不会更新到数据库的,会回滚的,所以我总结就是executeUpdate(sql)这个方法我们直接sql,和操作对象是不一样的的,具体我也没有研究 [b]问题补充:[/b] [code="java"] public void updateByIds(final Set<String> updateIds)throws DaoException{ try { getHibernateTemplate().execute(new HibernateCallback(){ final String hql="update Yaoyuepub y set y.state=2 where yaoyueid in (:yaoyueid)"; public Object doInHibernate(Session session) throws HibernateException, SQLException { Query query=session.createQuery(hql); query.setParameterList("yaoyueid", updateIds); query.executeUpdate(); return null; } } , true); } catch (Exception e) { e.printStackTrace(); throw new DaoException(this.getClassName()+e.getMessage()); } } [/code] 把上面的updateIds方法改成: [code="java"] public void updateByIds(final Set<String> updateIds)throws DaoException{ try { DetachedCriteria dc=DetachedCriteria.forClass(Yaoyuepub.class); dc.add(Restrictions.in("yaoyueid", updateIds)); List<Yaoyuepub> yaoyuepubs=select(dc); for(Yaoyuepub y:yaoyuepubs){ update(y); } } catch (Exception e) { e.printStackTrace(); throw new DaoException(this.getClassName()+e.getMessage()); } } [/code] 所有的调用都不变,spring事务就起作用了,说明自己createQuery然后executeUpdate是不被事务管理的,后其他都没有关系
遍历泛型List,应该返回什么类型
泛型不支持 用《T》代替了 方法一 public static 《T》 List《T》 query(String sql, Class《T》 clazz) { Connection conn = null; PreparedStatement pstmt = null; ResultSet rs = null; Object tempStr = null; List《T》 list = new ArrayList《T》(); try { conn = DBConnectUtils.getConnection(); pstmt = conn.prepareStatement(sql); rs = pstmt.executeQuery(); while (rs.next()) { // newInstance实际上是把new这个方式分解为两步,即,首先调用class的加载方法加载某个类,然后实例化。 // 我们可以在调用class的静态加载方法forName时获得更好的灵活性,提供给了我们降耦的手段。 // newInstance: 弱类型。低效率。只能调用无参构造。 // new: 强类型。相对高效。能调用任何public构造。 T obj = clazz.newInstance(); if (obj instanceof String) { // ResultSet的下标从1开始 obj = (T) rs.getString(1); } else { // Field 提供有关类或接口的单个字段的信息,以及对它的动态访问权限 // getDeclaredFields()返回Class中所有的字段,包括私有字段 // getFields 只返回公共字段,即有public修饰的字段 // field,域是一种属性,可以是一个类变量,一个对象变量,一个对象方法变量或者是一个函数的参数。 Field[] fields = obj.getClass().getDeclaredFields(); // 遍历域 for (Field field : fields) { try { // 反射获取对象成员的字段值 tempStr = rs.getObject(field.getName()); } catch (SQLException e) { tempStr = ""; } // 置是否允许访问,而不是修改原来的访问权限修饰词 field.setAccessible(true); // 把对象的属性数据封装到对象中 BeanUtils.setProperty(obj, field.getName(), tempStr); } } list.add(obj); } } catch (Exception e) { e.printStackTrace(); } finally { DBCloseUtils.closeCSR(conn, pstmt, rs); } return list; } 方法二 public static 《T》 List《T》 query(String sql, Class《T》 clazz, Object[] parameters) { Connection conn = null; PreparedStatement pstmt = null; ResultSet rs = null; ResultSetMetaData metaData = null; List《T》 list = new ArrayList《T》(); int index = 1; try { pstmt = conn.prepareStatement(sql); if (parameters != null && parameters.length != 0) { for (int i = 0; i < parameters.length; i++) { // pstmt.setObject(第几个参数, 替换成什么); pstmt.setObject(index, parameters[i]); } } rs = pstmt.executeQuery(sql); // 封装resultset metaData = rs.getMetaData(); // 取出列的信息 int columnLength = metaData.getColumnCount(); // 获取列数 while (rs.next()) { // 通过反射机制创建一个对象 T result = clazz.newInstance(); for (int i = 0; i < columnLength; i++) { String metaDataKey = metaData.getColumnName(i + 1); Object resultsetValue = rs.getObject(metaDataKey); if (resultsetValue == null) { resultsetValue = ""; } Field field = clazz.getDeclaredField(metaDataKey); field.setAccessible(true); field.set(result, resultsetValue); } list.add(result); } } catch (Exception e) { e.printStackTrace(); } finally { DBCloseUtils.closeCSR(conn, pstmt, rs); } return list; }
Servlet实现排队处理视频转换请求中的疑问,贴代码请斧正!
项目需求:客户端上传视频(*.avi),server将请求排队,然后一个一个排队处理转换任务. 前面问过该问题,现在自己实现,由于多线程不精通. 如下实现该排队需求,自己感觉不太准确,有问题,请指出,并给个解决方法. (tip,没有servlet的单线程模式或将dopost方法synchronied,视乎这样做是由系统将请求排队,request请求不能立即得到回复! :) ) 1.TaskBean 写了一个bean,这个bean用来存储了转换任务的属性. [code="java"]package videoconvert; public class TaskBean { private String videoPath; private String flvPath; private boolean isConverting; public String getVideoPath() { return videoPath; } public void setVideoPath(String videoPath) { this.videoPath = videoPath; } public String getFlvPath() { return flvPath; } public void setFlvPath(String flvPath) { this.flvPath = flvPath; } public boolean getIsConverting() { return isConverting; } public void setIsConverting(boolean isConverting) { this.isConverting = isConverting; } }[/code] 2.VideoConvert 这是个servlet,用来排队请求,并调度转换工具进行转换. [code="java"]package videoconvert; import java.io.IOException; import java.io.PrintWriter; import java.util.Collections; import java.util.LinkedList; import java.util.List; import java.util.Timer; import java.util.TimerTask; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class VideoConvert extends HttpServlet { private static final long serialVersionUID = 6312986385178354217L; private static Logger logger = LoggerFactory.getLogger(VideoConvert.class); private static LinkedList<TaskBean> taskStack = new LinkedList<TaskBean>(); public VideoConvert() { super(); } @Override public void init() throws ServletException { // TODO Auto-generated method stub super.init(); new Timer().schedule(new TimerTask() { public void run() { checkTaskList();[color=red]//这里按时间间隔检查栈.并取出task来执行.[/color] } }, 0, 10000); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doPost(request, response); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { if (request.getRemoteAddr().equals("127.0.0.1")) { TaskBean task = new TaskBean(); String videoPath = (String) request.getAttribute("VideoPath"); String flvPath = (String) request.getAttribute("FlvPath"); if (null != videoPath && null != flvPath) { task.setVideoPath(videoPath); task.setFlvPath(flvPath); task.setIsConverting(false); synchronized (taskStack) { [color=red] //多线程以taskStack栈作为同步量,当持有taskStack对象才添加任务进栈[/color] taskStack.addLast(task); logger.info("add task to queue!"); } } else { logger.info("the paramters are null!"); } } else { logger.info("visit is illegal!"); } response.setContentType("text/html; charset=UTF-8"); PrintWriter pw = response.getWriter(); pw.write("上传视频成功,等待转换....") pw.flush(); } //这个是timer触发的任务,取出stack中的一个任务,然后检查是否在转换中,如果没有就调用工具进行转换. private void checkTaskList() { synchronized (taskStack) { [color=red]//这里感觉不准确,因为同步块里面,Timer新建的了一个线程p1来调用外 //部工具 // FFmpeg.并且会(process.waitFor();)等待FFmepg运行完成来返回结果. 所以在调 // 用外部工具的整个过程都占用了同步量(taskStack).所以应该如何改进...[/color] TaskBean task = taskStack.peekFirst(); if (null != task) { if (!task.getIsConverting()) { task.setIsConverting(true); executProcess(task); } } } } private void executProcess(TaskBean task) { MediaUtility mu = new MediaUtility(); //在类MediaUtility 中调用新建线程调用工具,并waitfor()结果 if (mu.video2Flv(task.getVideoPath(), task.getFlvPath())) { taskStack.removeFirst(); logger.info("achieve video convert,removeFirst task!"); } else { logger.error("video convert fail!"); taskStack.removeFirst(); } } }[/code] 3.调用工具的类 MediaUtility [code="java"]package videoconvert; import java.io.BufferedReader; import java.io.File; import java.io.FileOutputStream; import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class MediaUtility { private static Logger logger = LoggerFactory.getLogger(MediaUtility.class); public boolean video2Flv(String videoPath, String flvPath) { if (!checkfile(videoPath)) { logger.error(videoPath + " is not file!"); return false; } String cmdStr = "ffmpeg -i " + videoPath + " " + flvPath; logger.info(cmdStr); logger.info("Starting convert video to flv...."); BufferedReader ffmpegOut = null; try { Process process = Runtime.getRuntime().exec(cmdStr); // ffmpegOut = new BufferedReader(new InputStreamReader(process // .getInputStream())); ffmpegOut = new BufferedReader(new InputStreamReader(process .getErrorStream())); // FileWriter fileOut = new FileWriter(new File("c:/F.txt")); String dLine = ""; while ((dLine = ffmpegOut.readLine()) != null) { logger.info(dLine); // fileOut.write(dLine); } // fileOut.close(); process.waitFor(); logger.info("***************************** end convert video *************************"); ffmpegOut.close(); return true; } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); return false; } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); return false; } finally { try { if (null != ffmpegOut) { ffmpegOut.close(); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } public static boolean checkfile(String path) { File file = new File(path); if (!file.isFile()) { return false; } return true; } // public static void main(String[] args) { // boolean bb = video2Flv("d:/ffmpeg/uploadVideo/Video1.wmv", // "d:/ffmpeg/convertedVideo/pp1.flv"); // logger.info("the bb result is " + bb); // boolean cc = video2Flv("d:/ffmpeg/uploadVideo/Video2.wmv", // "d:/ffmpeg/convertedVideo/pp2.flv"); // logger.info("the cc result is " + cc); // }[/code] 如上面的代码.上面的代码每次只能有一个视频在转换,如果想改进为最多同时有3个或者6个任务在执行呢? 此时是否要再设置一个信号量呢? [b]问题补充:[/b] [quote]放一个线程池(ThreadPool),可以解决你的问题,每次把你的任务丢到线程池里面。[/quote] 只知道连接数据库用到线程池.请求排队也可以用线程池?有这样的应用吗? 8) 并且具体如何用,能给个例子吗? [b]问题补充:[/b] [quote]jdk的cocurrent里面有现成的。 Java代码 queue = new LinkedBlockingQueue<Runnable>(1000); threadPool = new ThreadPoolExecutor(5, 10, 10, TimeUnit.SECONDS, queue); 这样就定义了一个线程池。 Java代码 threadPool.execute(runnable); 这样就放入线程池一个Runnable了,就可以满足你的需求了。[/quote] 感谢taopian的热心回复,马上看jdk的cocurrent. :) [b]问题补充:[/b] [quote]jdk的cocurrent里面有现成的。 [/quote] 谢谢了,cocurrent包,感觉很好,应该就是解决问题的办法了. :idea: 另外,我还有一个不好很明白,就是 ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, RejectedExecutionHandler handler) 构造函数中的 BlockingQueue<Runnable> workQueue的作用? 感觉JVM可以在内部维护这个队列,不用释放出接口来. 当然尽管API上讲了" 大队列 用小池, 小队列 用大池," 可以提高资源利用率.然而现在还不是很理解.后面在实践中体会了. 嘿嘿 [b]问题补充:[/b] 先问再吃饭. :D [quote]BlockingQueue<Runnable> workQueue 这个就是放一个队列,任务扔到队列里面,可以对并发做控制。 把这个队列暴露出来,能够让你进行很好的控制,并且你可以继承BlockingQueue,来加入你自己需要的功能,:)。[/quote] 嗯,是的,可以自己继承BlockingQueue,再增加一些自己的功能,然后放入executor中去. 面向接口 :) 现在我已经可以顺利,并准确的运行了. 最后一个疑问: executor.excute(new Runnable(){ public void run(){ run 中的变量要求是final的.final变量的GC时间是否会有影响呢? 或者有别的更好解决方法 } } ) 我是这样的改的: 这个bean被迫为final的了.呵呵,有更好的方法吗? [code="java"]if (null != videoPath && null != flvPath) { final TaskBean task = new TaskBean(); task.setVideoPath(videoPath); task.setFlvPath(flvPath); threadPool.execute(new Runnable(){ public void run(){ MediaUtility.video2Flv(task.getVideoPath(), task.getFlvPath()); } });[/code] 哎呀,罗嗦了,吃饭先..... :D
【mybatis generator的报错】前期配置问题!!!!!官方文件看了一直也一头雾水
错误如下 Description Resource Path Location Type The content of element type "context" must match "(property*,plugin*,commentGenerator?,(connectionFactory|jdbcConnection),javaTypeResolver?,javaModelGenerator,sqlMapGenerator?,javaClientGenerator?,table+)". generatorConfig.xml /oracle/generator line 4 XML Problem 指向的代码错误是这样的 ``` <generatorConfiguration> <context id="oracleTables" defaultModelType="hierachical" targetRuntime="MyBatis3"> ``` 错误指向context id 改了半天一直报错。。难道是pom.xml的代码顺序问题?? 补源代码 ``` <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN" "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd"> <generatorConfiguration> <context id="oracleTables" defaultModelType="hierachical" targetRuntime="MyBatis3"> <!-- 自动识别数据库关键字段,默认false --> <property name="autoDelimitKeywords" value="false"/> <!-- 生成的Java文件的编码 --> <property name="javaFileEncoding" value="UTF-8"/> <!-- 格式化XML代码 --> <property name="xmlFormatter" value="org.mybatis.generator.api.dom.DefaultXmlFormatter"/> <!-- 指明数据库的用于标记数据库对象名的符号 --> <property name="beginningDelimiter" value='"'/> <property name="endingDelimiter" value='"'/> <!-- 连接oracle --> <jdbcConnection connectionURL="jdbc:oracle:thin:@localhost:1521:orcl" driverClass="oracle.jdbc.driver.OracleDriver" password="S123456" userId="c##refeal" /> <!-- Java类型处理器 --> <javaTypeResolver type="org.mybatis.generator.internal.types.JavaTypeResolverDefaultImpl"> <property name="forceBigDecimals" value="false"/> </javaTypeResolver> <!-- Java模型创建器 --> <javaModelGenerator targetPackage="com.SJY.domain" targetProject="src/main/java" /> <!-- for mabatis3 自动为每个生成的类创建一个构造方法 --> <property name="constructorBased" value="false"/> <!-- 在targetPachage的基础上,根据数据库的schema再生成一层package,最终生成的类放到这个package下 --> <property name="enableSubPackages" value="true"/> <!-- for MyBatis3 是否创建一个不可变类 --> <property name="immutable" value="false"/> <!-- 设置是否在getter方法中,对String类型字段调用trim()方法 --> <property name="rootClass" value="com.sjy.domain"/> <!-- 生成SQLmap的XML文件生成器 --> <sqlMapGenerator targetPackage="com.SJY.dao" targetProject="src/main/resources" /> <!-- 在targetPackage的基础上,根据数据库的schema再生成一层package --> <property name="enableSubPackages" value="true"/> <!-- 生成mapper接口 --> <javaClientGenerator targetPackage="com.SJY.domain" targetProject="src/main/java" type="XMLMAPPER" /> <!-- 在targetPackage的基础上,根据数据库的schema再生成一层package --> <property name="enableSubPackages" value="true"/> <!-- 与数据库相对应 --> <table schema="" tableName="SJY_YH_YHXXB" domainObjectName="YH_YHXXB" mapperName="YH_YHXXBMapper" enableUpdateByExample="true" enableDeleteByExample="true" enableSelectByExample="true" selectByExampleQueryId="true"> <generatedKey column="USERID" sqlStatement="SELECT SJY_YH_YHXXB_SEQUENCE.nextval AS USERID from DUAL"/> <columnOverride column="USERID" property="???" /> </table> </context> </generatorConfiguration> ``` 表字段暂时可以无视吧
recycview中添加底部按钮问题。
我就想在这个recycview中底部添加两个按钮 项目地址链接: https://pan.baidu.com/s/13EzJZ8CrRL6xRiFjUxJXqw 提取码: qjet ![图片说明](https://img-ask.csdn.net/upload/201903/14/1552547394_832120.png) ``` public class CollectFragment extends Fragment { public RecyclerView mCollectRecyclerView;//定义RecyclerView //定义以goodsentity实体类为对象的数据集合 private ArrayList<GoodsEntity> goodsEntityList = new ArrayList<GoodsEntity>(); //自定义recyclerveiw的适配器 private CollectRecycleAdapter mCollectRecyclerAdapter; private static ChangeFragment mChange; public static CollectFragment newInstance(ChangeFragment changeFragment) { mChange = changeFragment; Bundle args = new Bundle(); CollectFragment fragment = new CollectFragment(); fragment.setArguments(args); return fragment; } @Nullable @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { //获取fragment的layout View view = inflater.inflate(R.layout.recyclerview, container, false); //对recycleview进行配置 return view; } @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); initRecyclerView(view); //模拟数据 initData(); } /** * TODO 模拟数据 */ private void initData() { for (int i=0;i<10;i++){ GoodsEntity goodsEntity=new GoodsEntity(); goodsEntity.setGoodsName("模拟数据"+i); goodsEntity.setGoodsPrice("100"+i); goodsEntityList.add(goodsEntity); } } /** * TODO 对recycleview进行配置 */ private void initRecyclerView(View view) { //获取RecyclerView mCollectRecyclerView=view.findViewById(R.id.collect_recyclerView); //创建adapter mCollectRecyclerAdapter = new CollectRecycleAdapter(getActivity(), goodsEntityList); //给RecyclerView设置adapter mCollectRecyclerView.setAdapter(mCollectRecyclerAdapter); //设置layoutManager,可以设置显示效果,是线性布局、grid布局,还是瀑布流布局 //参数是:上下文、列表方向(横向还是纵向)、是否倒叙 mCollectRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity(), LinearLayoutManager.VERTICAL, false)); //设置item的分割线 mCollectRecyclerView.addItemDecoration(new DividerItemDecoration(getActivity(),DividerItemDecoration.VERTICAL)); //RecyclerView中没有item的监听事件,需要自己在适配器中写一个监听事件的接口。参数根据自定义 mCollectRecyclerAdapter.setOnItemClickListener(new CollectRecycleAdapter.OnItemClickListener() { @Override public void OnItemClick(View view, GoodsEntity data) { //此处进行监听事件的业务处理 Toast.makeText(getActivity(),"我是item",Toast.LENGTH_SHORT).show(); mChange.changeAttractionsContent(); } }); } } ``` ``` public class CollectRecycleAdapter extends RecyclerView.Adapter<CollectRecycleAdapter.myViewHodler> { private Context context; private ArrayList<GoodsEntity> goodsEntityList; //创建构造函数 public CollectRecycleAdapter(Context context, ArrayList<GoodsEntity> goodsEntityList) { //将传递过来的数据,赋值给本地变量 this.context = context;//上下文 this.goodsEntityList = goodsEntityList;//实体类数据ArrayList } /** * 创建viewhodler,相当于listview中getview中的创建view和viewhodler * * @param parent * @param viewType * @return */ @Override public myViewHodler onCreateViewHolder(ViewGroup parent, int viewType) { //创建自定义布局 View itemView = View.inflate(context, R.layout.item_content, null); return new myViewHodler(itemView); } /** * 绑定数据,数据与view绑定 * * @param holder * @param position */ @Override public void onBindViewHolder(myViewHodler holder, int position) { //根据点击位置绑定数据 GoodsEntity data = goodsEntityList.get(position); // holder.mItemGoodsImg; holder.mItemGoodsName.setText(data.goodsName);//获取实体类中的name字段并设置 holder.mItemGoodsPrice.setText(data.goodsPrice);//获取实体类中的price字段并设置 } /** * 得到总条数 * * @return */ @Override public int getItemCount() { return goodsEntityList.size(); } //自定义viewhodler class myViewHodler extends RecyclerView.ViewHolder { private ImageView mItemGoodsImg; private TextView mItemGoodsName; private TextView mItemGoodsPrice; public myViewHodler(View itemView) { super(itemView); mItemGoodsImg = itemView.findViewById(R.id.tx_news_simple_photos_01); mItemGoodsName = itemView.findViewById(R.id.tx_news_simple_photos_title); mItemGoodsPrice = itemView.findViewById(R.id.tx_news_simple_photos_time); //点击事件放在adapter中使用,也可以写个接口在activity中调用 //方法一:在adapter中设置点击事件 itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //可以选择直接在本位置直接写业务处理 //Toast.makeText(context,"点击了xxx",Toast.LENGTH_SHORT).show(); //此处回传点击监听事件 if(onItemClickListener!=null){ onItemClickListener.OnItemClick(v, goodsEntityList.get(getLayoutPosition())); } } }); } } /** * 设置item的监听事件的接口 */ public interface OnItemClickListener { /** * 接口中的点击每一项的实现方法,参数自己定义 * * @param view 点击的item的视图 * @param data 点击的item的数据 */ public void OnItemClick(View view, GoodsEntity data); } //需要外部访问,所以需要设置set方法,方便调用 private OnItemClickListener onItemClickListener; public void setOnItemClickListener(OnItemClickListener onItemClickListener) { this.onItemClickListener = onItemClickListener; } } ```
爬虫福利二 之 妹子图网MM批量下载
爬虫福利一:27报网MM批量下载    点击 看了本文,相信大家对爬虫一定会产生强烈的兴趣,激励自己去学习爬虫,在这里提前祝:大家学有所成! 目标网站:妹子图网 环境:Python3.x 相关第三方模块:requests、beautifulsoup4 Re:各位在测试时只需要将代码里的变量 path 指定为你当前系统要保存的路径,使用 python xxx.py 或IDE运行即可。
Java学习的正确打开方式
在博主认为,对于入门级学习java的最佳学习方法莫过于视频+博客+书籍+总结,前三者博主将淋漓尽致地挥毫于这篇博客文章中,至于总结在于个人,实际上越到后面你会发现学习的最好方式就是阅读参考官方文档其次就是国内的书籍,博客次之,这又是一个层次了,这里暂时不提后面再谈。博主将为各位入门java保驾护航,各位只管冲鸭!!!上天是公平的,只要不辜负时间,时间自然不会辜负你。 何谓学习?博主所理解的学习,它
程序员必须掌握的核心算法有哪些?
由于我之前一直强调数据结构以及算法学习的重要性,所以就有一些读者经常问我,数据结构与算法应该要学习到哪个程度呢?,说实话,这个问题我不知道要怎么回答你,主要取决于你想学习到哪些程度,不过针对这个问题,我稍微总结一下我学过的算法知识点,以及我觉得值得学习的算法。这些算法与数据结构的学习大多数是零散的,并没有一本把他们全部覆盖的书籍。下面是我觉得值得学习的一些算法以及数据结构,当然,我也会整理一些看过...
大学四年自学走来,这些私藏的实用工具/学习网站我贡献出来了
大学四年,看课本是不可能一直看课本的了,对于学习,特别是自学,善于搜索网上的一些资源来辅助,还是非常有必要的,下面我就把这几年私藏的各种资源,网站贡献出来给你们。主要有:电子书搜索、实用工具、在线视频学习网站、非视频学习网站、软件下载、面试/求职必备网站。 注意:文中提到的所有资源,文末我都给你整理好了,你们只管拿去,如果觉得不错,转发、分享就是最大的支持了。 一、PDF搜索网站推荐 对于大部
linux系列之常用运维命令整理笔录
本博客记录工作中需要的linux运维命令,大学时候开始接触linux,会一些基本操作,可是都没有整理起来,加上是做开发,不做运维,有些命令忘记了,所以现在整理成博客,当然vi,文件操作等就不介绍了,慢慢积累一些其它拓展的命令,博客不定时更新 顺便拉下票,我在参加csdn博客之星竞选,欢迎投票支持,每个QQ或者微信每天都可以投5票,扫二维码即可,http://m234140.nofollow.ax.
比特币原理详解
一、什么是比特币 比特币是一种电子货币,是一种基于密码学的货币,在2008年11月1日由中本聪发表比特币白皮书,文中提出了一种去中心化的电子记账系统,我们平时的电子现金是银行来记账,因为银行的背后是国家信用。去中心化电子记账系统是参与者共同记账。比特币可以防止主权危机、信用风险。其好处不多做赘述,这一层面介绍的文章很多,本文主要从更深层的技术原理角度进行介绍。 二、问题引入  假设现有4个人
程序员接私活怎样防止做完了不给钱?
首先跟大家说明一点,我们做 IT 类的外包开发,是非标品开发,所以很有可能在开发过程中会有这样那样的需求修改,而这种需求修改很容易造成扯皮,进而影响到费用支付,甚至出现做完了项目收不到钱的情况。 那么,怎么保证自己的薪酬安全呢? 我们在开工前,一定要做好一些证据方面的准备(也就是“讨薪”的理论依据),这其中最重要的就是需求文档和验收标准。一定要让需求方提供这两个文档资料作为开发的基础。之后开发
网页实现一个简单的音乐播放器(大佬别看。(⊙﹏⊙))
今天闲着无事,就想写点东西。然后听了下歌,就打算写个播放器。 于是乎用h5 audio的加上js简单的播放器完工了。 欢迎 改进 留言。 演示地点跳到演示地点 html代码如下`&lt;!DOCTYPE html&gt; &lt;html&gt; &lt;head&gt; &lt;title&gt;music&lt;/title&gt; &lt;meta charset="utf-8"&gt
Python十大装B语法
Python 是一种代表简单思想的语言,其语法相对简单,很容易上手。不过,如果就此小视 Python 语法的精妙和深邃,那就大错特错了。本文精心筛选了最能展现 Python 语法之精妙的十个知识点,并附上详细的实例代码。如能在实战中融会贯通、灵活使用,必将使代码更为精炼、高效,同时也会极大提升代码B格,使之看上去更老练,读起来更优雅。 1. for - else 什么?不是 if 和 else 才
数据库优化 - SQL优化
前面一篇文章从实例的角度进行数据库优化,通过配置一些参数让数据库性能达到最优。但是一些“不好”的SQL也会导致数据库查询变慢,影响业务流程。本文从SQL角度进行数据库优化,提升SQL运行效率。 判断问题SQL 判断SQL是否有问题时可以通过两个表象进行判断: 系统级别表象 CPU消耗严重 IO等待严重 页面响应时间过长
2019年11月中国大陆编程语言排行榜
2019年11月2日,我统计了某招聘网站,获得有效程序员招聘数据9万条。针对招聘信息,提取编程语言关键字,并统计如下: 编程语言比例 rank pl_ percentage 1 java 33.62% 2 c/c++ 16.42% 3 c_sharp 12.82% 4 javascript 12.31% 5 python 7.93% 6 go 7.25% 7
通俗易懂地给女朋友讲:线程池的内部原理
餐厅的约会 餐盘在灯光的照耀下格外晶莹洁白,女朋友拿起红酒杯轻轻地抿了一小口,对我说:“经常听你说线程池,到底线程池到底是个什么原理?”我楞了一下,心里想女朋友今天是怎么了,怎么突然问出这么专业的问题,但做为一个专业人士在女朋友面前也不能露怯啊,想了一下便说:“我先给你讲讲我前同事老王的故事吧!” 大龄程序员老王 老王是一个已经北漂十多年的程序员,岁数大了,加班加不动了,升迁也无望,于是拿着手里
经典算法(5)杨辉三角
写在前面: 我是 扬帆向海,这个昵称来源于我的名字以及女朋友的名字。我热爱技术、热爱开源、热爱编程。技术是开源的、知识是共享的。 这博客是对自己学习的一点点总结及记录,如果您对 Java、算法 感兴趣,可以关注我的动态,我们一起学习。 用知识改变命运,让我们的家人过上更好的生活。 目录一、杨辉三角的介绍二、杨辉三角的算法思想三、代码实现1.第一种写法2.第二种写法 一、杨辉三角的介绍 百度
腾讯算法面试题:64匹马8个跑道需要多少轮才能选出最快的四匹?
昨天,有网友私信我,说去阿里面试,彻底的被打击到了。问了为什么网上大量使用ThreadLocal的源码都会加上private static?他被难住了,因为他从来都没有考虑过这个问题。无独有偶,今天笔者又发现有网友吐槽了一道腾讯的面试题,我们一起来看看。 腾讯算法面试题:64匹马8个跑道需要多少轮才能选出最快的四匹? 在互联网职场论坛,一名程序员发帖求助到。二面腾讯,其中一个算法题:64匹
面试官:你连RESTful都不知道我怎么敢要你?
面试官:了解RESTful吗? 我:听说过。 面试官:那什么是RESTful? 我:就是用起来很规范,挺好的 面试官:是RESTful挺好的,还是自我感觉挺好的 我:都挺好的。 面试官:… 把门关上。 我:… 要干嘛?先关上再说。 面试官:我说出去把门关上。 我:what ?,夺门而去 文章目录01 前言02 RESTful的来源03 RESTful6大原则1. C-S架构2. 无状态3.统一的接
为啥国人偏爱Mybatis,而老外喜欢Hibernate/JPA呢?
关于SQL和ORM的争论,永远都不会终止,我也一直在思考这个问题。昨天又跟群里的小伙伴进行了一番讨论,感触还是有一些,于是就有了今天这篇文。 声明:本文不会下关于Mybatis和JPA两个持久层框架哪个更好这样的结论。只是摆事实,讲道理,所以,请各位看官勿喷。 一、事件起因 关于Mybatis和JPA孰优孰劣的问题,争论已经很多年了。一直也没有结论,毕竟每个人的喜好和习惯是大不相同的。我也看
SQL-小白最佳入门sql查询一
一 说明 如果是初学者,建议去网上寻找安装Mysql的文章安装,以及使用navicat连接数据库,以后的示例基本是使用mysql数据库管理系统; 二 准备前提 需要建立一张学生表,列分别是id,名称,年龄,学生信息;本示例中文章篇幅原因SQL注释略; 建表语句: CREATE TABLE `student` ( `id` int(11) NOT NULL AUTO_INCREMENT, `
项目中的if else太多了,该怎么重构?
介绍 最近跟着公司的大佬开发了一款IM系统,类似QQ和微信哈,就是聊天软件。我们有一部分业务逻辑是这样的 if (msgType = "文本") { // dosomething } else if(msgType = "图片") { // doshomething } else if(msgType = "视频") { // doshomething } else { // dosho
【图解经典算法题】如何用一行代码解决约瑟夫环问题
约瑟夫环问题算是很经典的题了,估计大家都听说过,然后我就在一次笔试中遇到了,下面我就用 3 种方法来详细讲解一下这道题,最后一种方法学了之后保证让你可以让你装逼。 问题描述:编号为 1-N 的 N 个士兵围坐在一起形成一个圆圈,从编号为 1 的士兵开始依次报数(1,2,3…这样依次报),数到 m 的 士兵会被杀死出列,之后的士兵再从 1 开始报数。直到最后剩下一士兵,求这个士兵的编号。 1、方
致 Python 初学者
文章目录1. 前言2. 明确学习目标,不急于求成,不好高骛远3. 在开始学习 Python 之前,你需要做一些准备2.1 Python 的各种发行版2.2 安装 Python2.3 选择一款趁手的开发工具3. 习惯使用IDLE,这是学习python最好的方式4. 严格遵从编码规范5. 代码的运行、调试5. 模块管理5.1 同时安装了py2/py35.2 使用Anaconda,或者通过IDE来安装模
“狗屁不通文章生成器”登顶GitHub热榜,分分钟写出万字形式主义大作
一、垃圾文字生成器介绍 最近在浏览GitHub的时候,发现了这样一个骨骼清奇的雷人项目,而且热度还特别高。 项目中文名:狗屁不通文章生成器 项目英文名:BullshitGenerator 根据作者的介绍,他是偶尔需要一些中文文字用于GUI开发时测试文本渲染,因此开发了这个废话生成器。但由于生成的废话实在是太过富于哲理,所以最近已经被小伙伴们给玩坏了。 他的文风可能是这样的: 你发现,
程序员:我终于知道post和get的区别
IT界知名的程序员曾说:对于那些月薪三万以下,自称IT工程师的码农们,其实我们从来没有把他们归为我们IT工程师的队伍。他们虽然总是以IT工程师自居,但只是他们一厢情愿罢了。 此话一出,不知激起了多少(码农)程序员的愤怒,却又无可奈何,于是码农问程序员。 码农:你知道get和post请求到底有什么区别? 程序员:你看这篇就知道了。 码农:你月薪三万了? 程序员:嗯。 码农:你是怎么做到的? 程序员:
《程序人生》系列-这个程序员只用了20行代码就拿了冠军
你知道的越多,你不知道的越多 点赞再看,养成习惯GitHub上已经开源https://github.com/JavaFamily,有一线大厂面试点脑图,欢迎Star和完善 前言 这一期不算《吊打面试官》系列的,所有没前言我直接开始。 絮叨 本来应该是没有这期的,看过我上期的小伙伴应该是知道的嘛,双十一比较忙嘛,要值班又要去帮忙拍摄年会的视频素材,还得搞个程序员一天的Vlog,还要写BU
加快推动区块链技术和产业创新发展,2019可信区块链峰会在京召开
      11月8日,由中国信息通信研究院、中国通信标准化协会、中国互联网协会、可信区块链推进计划联合主办,科技行者协办的2019可信区块链峰会将在北京悠唐皇冠假日酒店开幕。   区块链技术被认为是继蒸汽机、电力、互联网之后,下一代颠覆性的核心技术。如果说蒸汽机释放了人类的生产力,电力解决了人类基本的生活需求,互联网彻底改变了信息传递的方式,区块链作为构造信任的技术有重要的价值。   1
程序员把地府后台管理系统做出来了,还有3.0版本!12月7号最新消息:已在开发中有github地址
第一幕:缘起 听说阎王爷要做个生死簿后台管理系统,我们派去了一个程序员…… 996程序员做的梦: 第一场:团队招募 为了应对地府管理危机,阎王打算找“人”开发一套地府后台管理系统,于是就在地府总经办群中发了项目需求。 话说还是中国电信的信号好,地府都是满格,哈哈!!! 经常会有外行朋友问:看某网站做的不错,功能也简单,你帮忙做一下? 而这次,面对这样的需求,这个程序员
网易云6亿用户音乐推荐算法
网易云音乐是音乐爱好者的集聚地,云音乐推荐系统致力于通过 AI 算法的落地,实现用户千人千面的个性化推荐,为用户带来不一样的听歌体验。 本次分享重点介绍 AI 算法在音乐推荐中的应用实践,以及在算法落地过程中遇到的挑战和解决方案。 将从如下两个部分展开: AI 算法在音乐推荐中的应用 音乐场景下的 AI 思考 从 2013 年 4 月正式上线至今,网易云音乐平台持续提供着:乐屏社区、UGC
【技巧总结】位运算装逼指南
位算法的效率有多快我就不说,不信你可以去用 10 亿个数据模拟一下,今天给大家讲一讲位运算的一些经典例子。不过,最重要的不是看懂了这些例子就好,而是要在以后多去运用位运算这些技巧,当然,采用位运算,也是可以装逼的,不信,你往下看。我会从最简单的讲起,一道比一道难度递增,不过居然是讲技巧,那么也不会太难,相信你分分钟看懂。 判断奇偶数 判断一个数是基于还是偶数,相信很多人都做过,一般的做法的代码如下
日均350000亿接入量,腾讯TubeMQ性能超过Kafka
整理 | 夕颜出品 | AI科技大本营(ID:rgznai100) 【导读】近日,腾讯开源动作不断,相继开源了分布式消息中间件TubeMQ,基于最主流的 OpenJDK8开发的
8年经验面试官详解 Java 面试秘诀
    作者 | 胡书敏 责编 | 刘静 出品 | CSDN(ID:CSDNnews) 本人目前在一家知名外企担任架构师,而且最近八年来,在多家外企和互联网公司担任Java技术面试官,前后累计面试了有两三百位候选人。在本文里,就将结合本人的面试经验,针对Java初学者、Java初级开发和Java开发,给出若干准备简历和准备面试的建议。   Java程序员准备和投递简历的实
面试官如何考察你的思维方式?
1.两种思维方式在求职面试中,经常会考察这种问题:北京有多少量特斯拉汽车? 某胡同口的煎饼摊一年能卖出多少个煎饼? 深圳有多少个产品经理? 一辆公交车里能装下多少个乒乓球? 一
相关热词 c# plc s1200 c#里氏转换原则 c# 主界面 c# do loop c#存为组套 模板 c# 停掉协程 c# rgb 读取图片 c# 图片颜色调整 最快 c#多张图片上传 c#密封类与密封方法
立即提问